设置路径点
代码语言:javascript复制using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class WaypointsManager : MonoBehaviour {
Transform[] waypoints;
// Use this for initialization
void Start () {
waypoints = new Transform[transform.childCount];
int index = 0;
foreach (Transform t in transform)
{
waypoints[index] = t;
index ;
}
}
public Transform getNextWayPt()
{
if (waypoints != null && waypoints.Length > 0)
{
int index = Random.Range(0, waypoints.Length);
Debug.Log("index:" index);
if(index == waypoints.Length)
{
index--;
}
return waypoints[index];
}
else
{
return null;
}
}
}
目标上挂脚本
代码语言:javascript复制using UnityEngine;
using System.Collections;
using DG.Tweening;
public class ButterFlyController : MonoBehaviour {
public Transform selfObj;
public Transform target;
Rigidbody rigid;
ButterFlyAnimationController bfAnimController;
float turningFactor = 0.6f;
//float movingSpeed = 1f;
float landingDist = 1f;
float step = 0.3f;
float movingDuration = 0.1f;
float turningDuration = 0.1f;
public SphereCollider myCollider;
public WaypointsManager wayPtsManager;
float staticRadius = 1.3f;
float flyingRadius = 2.2f;
int castLayerMask;
int handLayerIndex;
Sequence currentSeq;
Vector3 avoidDir = Vector3.zero;
int landingSpotsLayer;
const int subseqCycle = 3;
int randSubseqCount = subseqCycle;
bool isTakingOff = false;
public bool testFly;
// Use this for initialization
void Start () {
myCollider.radius = staticRadius;
bfAnimController = GetComponent<ButterFlyAnimationController>();
rigid = GetComponent<Rigidbody>();
landingSpotsLayer = LayerMask.NameToLayer("landingSpots");
handLayerIndex = LayerMask.NameToLayer("Hands");
castLayerMask = ~(1 << landingSpotsLayer);
bfAnimController.idle();
if (testFly)
Invoke("chooseTargetAndTakeOff", 3);
}
// Update is called once per frame
void Update() {
//random Idle behaviour
if(!bfAnimController.isFlying() && !bfAnimController.isPrepareToIdle())
{
if (Random.Range(0, 10000) > 9900)
{
if (randSubseqCount == 0) {
randSubseqCount = subseqCycle;
bfAnimController.idle();
}
randSubseqCount--;
}
}
if(bfAnimController.isFlying())
myCollider.radius = flyingRadius;
else
myCollider.radius = staticRadius;
//if (!bfAnimController.isFlying())
//{
// chooseTargetAndTakeOff();
//}
}
public void takeOff() {
bfAnimController.stopIdling();
bfAnimController.takeOff();
Invoke("flyToTarget", 1.7f);
isTakingOff = false;
}
public void flyToTarget() {
Vector3 targetDir = (target.position - selfObj.position);
if (targetDir.magnitude < landingDist)
{
if(target.gameObject.layer == landingSpotsLayer)
{
Debug.Log("Landing!!");
landing();
return;
}
}
targetDir = targetDir.normalized;
currentSeq = DOTween.Sequence();
float avoidTendency = 0.65f;
Vector3 nextDir = Vector3.Slerp(selfObj.forward, (1- avoidTendency) * targetDir avoidTendency * avoidDir, turningFactor).normalized;
float forwardDampingFactor = Mathf.Max(Vector3.Dot(nextDir, selfObj.forward), 0);
Vector3 nextPos = selfObj.position nextDir * forwardDampingFactor * step;
currentSeq.Append(selfObj.DOMove(nextPos, movingDuration))
.Join(selfObj.DOLookAt(nextPos, turningDuration))
.AppendCallback(flyToTarget);
}
float landingDuration = 0.2f;
public void landing() {
Sequence mySequence = DOTween.Sequence();
Vector3 nextDir = selfObj.forward - Vector3.Dot(selfObj.forward, target.up) * target.up;
mySequence.Append(selfObj.DOMove(target.position target.up * 0f, landingDuration))
.Join(selfObj.DOLookAt(selfObj.position nextDir, landingDuration))
.AppendCallback(landed);
Invoke("playLandingAnimation", 0.7f);
}
public void playLandingAnimation()
{
bfAnimController.land();
}
public void landed()
{
Invoke("chooseTargetAndTakeOff", Random.Range(7f, 30f));
}
void OnCollisionEnter(Collision collision)
{
//Debug.Log("Collision!" collision.gameObject.name);
if (!bfAnimController.isFlying())
{
if (collision.gameObject.layer == handLayerIndex)
{
chooseTargetAndTakeOff();
}
}
else
{
if (currentSeq != null && currentSeq.IsPlaying())
{
avoidDir = (selfObj.position - collision.contacts[0].point).normalized;
currentSeq.Kill();
currentSeq = null;
flyToTarget();
}
}
}
void OnCollisionExit(Collision collision)
{
avoidDir = Vector3.zero;
}
void chooseTargetAndTakeOff()
{
if (!bfAnimController.isFlying() && !isTakingOff)
{
isTakingOff = true;
target = wayPtsManager.getNextWayPt();
while(Vector3.Distance(target.position,selfObj.position) < landingDist)
{
target = wayPtsManager.getNextWayPt();
}
takeOff();
}
}
}
动画控制
代码语言:javascript复制using UnityEngine;
using System.Collections;
public class ButterFlyAnimationController : MonoBehaviour {
Animator animator;
string flyingStateName = "Flying";
string takeOffTriggerName = "TakeOff";
string idleTriggerName = "toIdle";
// Use this for initialization
void Awake()
{
animator = GetComponent<Animator>();
}
public void takeOff()
{
animator.SetBool(flyingStateName, true);
animator.SetTrigger(takeOffTriggerName);
}
public void land()
{
animator.SetBool(flyingStateName, false);
}
public void idle()
{
animator.SetTrigger(idleTriggerName);
}
public void stopIdling()
{
animator.SetBool(idleTriggerName, false);
}
public bool isPrepareToIdle()
{
return animator.GetBool(idleTriggerName);
}
public bool isFlying()
{
return animator.GetBool(flyingStateName);
}
}