You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
6.2 KiB
C#
189 lines
6.2 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// This is an updated version to the original script from Malbers. It allows you to:
|
|
/// * set a random offset to the target position
|
|
/// * change the random offset at a given time interval
|
|
/// </summary>
|
|
namespace MalbersAnimations
|
|
{
|
|
[AddComponentMenu("Malbers/AI/Follow Target Extended")]
|
|
|
|
/// <summary> Simple follow target for the animal </summary>
|
|
public class FollowTargetExtended : MonoBehaviour
|
|
{
|
|
|
|
public enum TargetType
|
|
{
|
|
[Tooltip("Use the specific target gameobject as target")]
|
|
GameObject,
|
|
|
|
[Tooltip("Use the first found gameobject as target which has the specified target tag. Usually the Player tag")]
|
|
Tag
|
|
}
|
|
|
|
[Header("Selection")]
|
|
|
|
public TargetType type = TargetType.GameObject;
|
|
|
|
[Tooltip("An optional target tag. If no target is explicitly set, then the target with this specified target name will be used")]
|
|
public string targetTag;
|
|
|
|
[Tooltip("The target gameobject. Either explicitly specified or defined at start depending on the target tag")]
|
|
public Transform targetGameObject;
|
|
|
|
[Tooltip("In case the target is instantiated at startup, setting this to true will try to find the target with the specified tag during the Update method")]
|
|
public bool delayedTargetSearch = false;
|
|
|
|
[Header("Settings")]
|
|
|
|
public float stopDistance = 3;
|
|
ICharacterMove animal;
|
|
|
|
[Tooltip("Activate having random positions around the target")]
|
|
public bool targetRandomness = false;
|
|
|
|
[Tooltip("Number of seconds at which the target position changes. Use 0 for keeping the initial position")]
|
|
public float updateInterval = 0f;
|
|
|
|
[Tooltip("Minimum random distance from the target")]
|
|
[Range(0f,10f)]
|
|
public float randomDistanceMin = 1f;
|
|
|
|
[Tooltip("Maximum random distance from the target")]
|
|
[Range(0f, 10f)]
|
|
public float randomDistanceMax = 3f;
|
|
|
|
private Vector3 targetDistanceOffset = Vector3.zero;
|
|
|
|
/// <summary>
|
|
/// If a key is defined, then this key will be used for toggling the following.
|
|
/// </summary>
|
|
public string followToogleKey;
|
|
|
|
/// <summary>
|
|
/// Whether following is enabled or not
|
|
/// </summary>
|
|
public bool followEnabled = true;
|
|
|
|
// Use this for initialization
|
|
void Start()
|
|
{
|
|
animal = GetComponentInParent<ICharacterMove>();
|
|
|
|
// randomize target position
|
|
if (targetRandomness)
|
|
{
|
|
// initial target position
|
|
CalculateTargetPositionOffset();
|
|
|
|
// periodic target position changes
|
|
if(updateInterval > 0) {
|
|
|
|
StartCoroutine(UpdateTargetPositionOffset());
|
|
|
|
}
|
|
}
|
|
|
|
// find target in case it should be found by tag
|
|
FindTargetByTag();
|
|
}
|
|
|
|
private void FindTargetByTag()
|
|
{
|
|
if (!targetGameObject && type == TargetType.Tag && targetTag != null)
|
|
{
|
|
targetTag = targetTag.Trim();
|
|
|
|
if (!string.IsNullOrEmpty(targetTag))
|
|
{
|
|
GameObject[] players = GameObject.FindGameObjectsWithTag(targetTag);
|
|
foreach (GameObject player in players)
|
|
{
|
|
if (player.activeInHierarchy)
|
|
{
|
|
targetGameObject = player.transform;
|
|
|
|
Debug.Log("Target found for " + transform.name + ": " + targetGameObject.transform.name);
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
if (!targetGameObject)
|
|
{
|
|
// search until a target is found
|
|
if (delayedTargetSearch)
|
|
{
|
|
FindTargetByTag();
|
|
|
|
Debug.Log("Delayed target update. Target = " + targetGameObject);
|
|
}
|
|
|
|
// still no target found, abort
|
|
if( !targetGameObject)
|
|
return;
|
|
}
|
|
|
|
if (Input.anyKeyDown)
|
|
{
|
|
if (followToogleKey.Length > 0 && Input.inputString == followToogleKey)
|
|
{
|
|
followEnabled = !followEnabled;
|
|
}
|
|
}
|
|
|
|
if (!followEnabled)
|
|
return;
|
|
|
|
Vector3 targetPosition = targetGameObject.position;
|
|
if( targetRandomness) {
|
|
|
|
// calculate the new target position depending on the offset from the local position
|
|
// targetPosition = target.transform.TransformPoint( target.localPosition + targetDistanceOffset);
|
|
targetPosition = targetGameObject.localPosition + targetDistanceOffset;
|
|
|
|
// Debug.DrawLine(transform.position, targetPosition, Color.yellow);
|
|
|
|
}
|
|
|
|
Vector3 Direction = targetPosition - transform.position; //Calculate the direction from the animal to the target
|
|
float distance = Vector3.Distance(transform.position, targetGameObject.position); //Calculate the distance..
|
|
animal.Move(distance > stopDistance ? Direction : Vector3.zero); //Move the Animal if we are not on the Stop Distance Radius
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
animal.Move(Vector3.zero); //In case this script gets disabled stop the movement of the Animal
|
|
}
|
|
|
|
private IEnumerator UpdateTargetPositionOffset() {
|
|
|
|
while (true)
|
|
{
|
|
yield return new WaitForSeconds(updateInterval);
|
|
|
|
CalculateTargetPositionOffset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a random local offset from the target
|
|
/// </summary>
|
|
private void CalculateTargetPositionOffset()
|
|
{
|
|
float distance = Random.Range(randomDistanceMin, randomDistanceMax);
|
|
targetDistanceOffset = Random.insideUnitSphere.normalized * distance;
|
|
|
|
}
|
|
}
|
|
} |