简单用Behavior Designer插件实现:当敌人发现玩家后开始追踪玩家,当追上玩家时发动攻击
Behavior Designer自带了一些Task,但是要实现自己的需求,必须动手写自己的Task。
这个Demo用到三个自定义Task:
1. WithinSight (用于判断攻击目标是否在视线内)
using UnityEngine;
using System.Collections;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
[TaskCategory("Custom")]//此Task将显示在Custom栏目下
[TaskDescription("判断目标是否在视野中")]
public class WithinSight : Conditional//继承Behavior Designer的Conditional类,将会显示在BehaviorDesigner Task面板中的Conditional栏目下
{
public string targetTag;//目标的Tag
public float viewLength;//视野范围
public SharedTransform target;//SharedTransform是BehaviorDesigner的类型,对应Transform类型。顾名思义,就是将此变量共享,以便其它Task访问,需要在Variables面板中定义出一个同类型变量以接收此变量
private Transform[] possibleTargets;//所有targetTag的目标
public override void OnAwake()
{
var targets = GameObject.FindGameObjectsWithTag(targetTag);
possibleTargets = new Transform[targets.Length];
for (int i = 0; i < targets.Length; i++)
{
possibleTargets[i] = targets[i].transform;
}
}
public override TaskStatus OnUpdate()
{
for (int i = 0; i < possibleTargets.Length; i++)
{
if (withinSight(possibleTargets[i], viewLength))
{
target.Value = possibleTargets[i];
return TaskStatus.Success;//如果找到目标返回Task成功
}
}
return TaskStatus.Failure;//如果没找到目标返回Task失败
}
public bool withinSight(Transform targetTransform, float viewLength)
{
RaycastHit rayCast;
Vector3 direction = targetTransform.position - transform.position;
var hit = Physics.Raycast(transform.position, direction, out rayCast, viewLength);
if(hit && rayCast.collider.tag == "Player")
{
return true;
}
else
{
return false;
}
}
}
2. MoveToward(用于追赶目标)
using UnityEngine;
using System.Collections;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
[TaskCategory("Custom")]
[TaskDescription("移动")]
public class MoveToward : Action {
public float speed = 0;
//[RequiredField]
public SharedTransform target;
public override TaskStatus OnUpdate()
{
if((transform.position.x-target.Value.position.x)<0.1f)
{
return TaskStatus.Success;
}
transform.position += transform.forward * (speed * Time.deltaTime);
return TaskStatus.Running;
}
}
3. Attack (攻击)
using UnityEngine;
using System.Collections;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
[TaskCategory("Custom")]
[TaskDescription("攻击")]
public class Attack : Action {
private bool isAttack;
private GameObject weapon;
private float fireRate = 1.0f;
public override void OnAwake()
{
weapon = transform.FindChild("RayLine").gameObject;
}
public override void OnStart()
{
}
public override TaskStatus OnUpdate()
{
fireRate -= Time.deltaTime;
if(fireRate < 0)
{
Fire();
fireRate = 1.0f;
return TaskStatus.Running;
}
else
{
if (weapon.activeSelf)
weapon.SetActive(false);
}
return TaskStatus.Failure;
}
private void Fire()
{
weapon.SetActive(true);
}
}
4. 创建Repeater节点,勾选Repeat Forever让敌人实时判断
5.创建Sequence节点,此节点下的分支将从左到右逐个执行,遇到Task返回失败则不再往下执行
6. 在Sequence节点下创建三个自定义节点作为其子节点,对变量进行赋值。这里的Target变量需要共享给MoveToward节点用,所以要在Variable中定义一个Transform类型变量target,赋值给Target