可移动的AI角色基类
public class Vehicle : MonoBehaviour {
//行为列表
private Steering[] steerings;
public float maxSpeed = 10.0f;
public float maxForce = 100.0f;
protected float sqrMaxSpeed;
public float mass = 1;
public Vector3 velocity;
//转向速度
public float damping = 0.9f;
//计算间隔
public float computeInterval = 0.2f;
//是否在二维平面上
public bool isPlanar = true;
private Vector3 steeringForce;
protected Vector3 acceleration;
private float timer;
protected void Start() {
steeringForce = new Vector3 (0, 0, 0);
sqrMaxSpeed = maxSpeed * maxSpeed;
timer = 0;
steerings = GetComponents<Steering> ();
}
void Update() {
timer += Time.deltaTime;
steeringForce = new Vector3 (0, 0, 0);
if (timer > computeInterval) {
foreach (Steering s in steerings) {
if (s.enabled)
steeringForce += s.Force () * s.weight;
}
steeringForce = Vector3.ClampMagnitude (steeringForce, maxForce);
acceleration = steeringForce / mass;
timer = 0;
}
}
}
AI角色移动控制类
public class AILocomotion : Vehicle {
private CharacterController controller;
private Rigidbody theRigidbody;
public Vector3 moveDistance;
void Start() {
controller = GetComponent<CharacterController> ();
theRigidbody = GetComponent<Rigidbody> ();
moveDistance = new Vector3 (0, 0, 0);
base.Start ();
}
void FixedUpdate() {
velocity += acceleration * Time.fixedDeltaTime;
if (velocity.sqrMagnitude > sqrMaxSpeed)
velocity = velocity.normalized * maxSpeed;
moveDistance = velocity * Time.fixedDeltaTime;
if (isPlanar) {
velocity.y = 0;
moveDistance.y = 0;
}
if (controller != null)
controller.SimpleMove (velocity);
else if (theRigidbody == null || theRigidbody.isKinematic)
transform.position += moveDistance;
else
theRigidbody.MovePosition (theRigidbody.position + moveDistance);
if (velocity.sqrMagnitude > 0.00001f) {
Vector3 newForward = Vector3.Slerp (transform.forward, velocity, damping * Time.deltaTime);
if (isPlanar)
newForward.y = 0;
transform.forward = newForward;
}
//TODO 播放行走动画
}
}
操控行为的基类 (抽象类)
public abstract class Steering : MonoBehaviour {
public float weight = 1.0f;
void Start() {
}
void Update() {
}
public virtual Vector3 Force() {
return new Vector3 (0, 0, 0);
}
}
行为1: 靠近
public class SteeringForSeek : Steering {
public GameObject target;
//预期速度
private Vector3 desiredVelocity;
private Vehicle m_vehicle;
private float maxSpeed;
private bool isPlanar;
void Start() {
m_vehicle = GetComponent<Vehicle> ();
maxSpeed = m_vehicle.maxSpeed;
isPlanar = m_vehicle.isPlanar;
}
public override Vector3 Force ()
{
desiredVelocity = (target.transform.position - transform.position).normalized * maxSpeed;
if (isPlanar)
desiredVelocity.y = 0;
return (desiredVelocity - m_vehicle.velocity);
}
}
行为2:离开
public class SteeringForFlee : Steering {
public GameObject target;
public float fearDistance = 20;
private Vector3 desiredVelocity;
private Vehicle m_vehicle;
private float maxSpeed;
void Start() {
m_vehicle = GetComponent<Vehicle> ();
maxSpeed = m_vehicle.maxSpeed;
}
public override Vector3 Force() {
Vector3 Pos = new Vector3 (transform.position.x, 0, transform.position.z);
Vector3 targetPos = new Vector3 (target.transform.position.x, 0, target.transform.position.z);
if (Vector3.Distance (Pos, targetPos) > fearDistance)
return new Vector3 (0, 0, 0);
desiredVelocity = (transform.position - target.transform.position).normalized * maxSpeed;
return (desiredVelocity - m_vehicle.velocity);
}
}
行为3:抵达
public class SteeringForArrive : Steering {
private bool isPlanar = true;
public float arrivalDistance = 0.3f;
public float characterRadius = 1.2f;
public float slowDownDisatance;
public GameObject target;
private Vector3 desiredVelocity;
private Vehicle m_vehicle;
private float maxSpeed;
void Start() {
m_vehicle = GetComponent<Vehicle> ();
maxSpeed = m_vehicle.maxSpeed;
isPlanar = m_vehicle.isPlanar;
}
public override Vector3 Force() {
Vector3 toTarget = target.transform.position - transform.position;
Vector3 returnForce;
if (isPlanar)
toTarget.y = 0;
float distance = toTarget.magnitude;
if (distance > slowDownDisatance) {
desiredVelocity = toTarget.normalized * maxSpeed;
returnForce = desiredVelocity - m_vehicle.velocity;
} else {
// ??? cal new return forre 为什么要用距离减去两倍的速度
desiredVelocity = toTarget - m_vehicle.velocity;
returnForce = desiredVelocity - m_vehicle.velocity;
}
return returnForce;
}
}
网友评论