unity3d:路径点移动,使用dotween(模拟蝴蝶飞舞)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/luoyikun/article/details/88580462

设置路径点

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;
        }
    }
    
}

在这里插入图片描述

目标上挂脚本

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();
        }
    }

}

动画控制

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);
    }



}

猜你喜欢

转载自blog.csdn.net/luoyikun/article/details/88580462