Unity实战篇:实现LOL英雄的移动方式。

版权声明:转载请注明出处!不注明也无所谓,嘿嘿。 https://blog.csdn.net/qq_15020543/article/details/83277904

本来是一个很简单的需求,可是当自己做的时候,才知道有多少要注意的地方。

还是先上效果图吧。

方案一.

Vector3.Lerp的非匀速运动,PASS。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Move : MonoBehaviour {
    private RaycastHit hit;
    private Ray ray;
    private bool suc;
    private float startTime;
    private float dis;

    void FixedUpdate() {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            startTime = Time.time;
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            suc = Physics.Raycast(ray, out hit, 1000);
            dis = Vector3.Distance(transform.position, hit.point);
        }
        if(suc)
        {
            Debug.DrawLine(transform.position, hit.point, Color.red);
            float disCovered = (Time.time - startTime) ;
            float fracJourney = disCovered / dis;
            transform.position = Vector3.Lerp(transform.position, hit.point, fracJourney);
        }

    }
}

方案二.

Rigidbody.MovePostion的瞬移以及设置插值之后的非匀速运动,PASS。

方案三.(可行且推荐)

Vector3.MoveToward

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Move : MonoBehaviour {
    private RaycastHit hit;
    private Ray ray;
    private bool suc;

    void FixedUpdate() {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            suc = Physics.Raycast(ray, out hit, 1000);
        }

        if(suc)
        {
            transform.position = Vector3.MoveTowards(transform.position, hit.point, Time.fixedDeltaTime*8);
        }
        if(transform.position==hit.point)
        {
            suc = false;
        }
    }
}

方案四 万恶之源Transform.Translate(可行但不推荐)

先说一下遇到的坑,可能会因为速度过快而检测不到已经到达目的地而继续前进,所以用Distance函数来帮忙。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Movbe : MonoBehaviour {
    private RaycastHit hit;
    private Ray ray;
    private bool suc;
    private Vector3 dir;
    private float dis;
    // Use this for initialization
    void Start() {

        
    }

    // Update is called once per frame
    void FixedUpdate() {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            suc = Physics.Raycast(ray, out hit, 1000);
            dir = (hit.point - transform.position).normalized;
            dis = Vector3.Distance(transform.position, hit.point);
        }
        if(suc)
        {
            if (Vector3.Distance(transform.position, hit.point) > 0.5f)
            {
                Debug.DrawLine(transform.position, hit.point, Color.red);
                transform.Translate(dir * Time.fixedDeltaTime * 20);
            }
            else
            {
                transform.position = hit.point;
                suc = false;
            }
        }
    }
}

然后使用LookAt函数使角色转向

最终方案:

利用混合树具体实现

代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Move : MonoBehaviour
{
    private RaycastHit hit;
    private Ray ray;
    private bool suc;
    private Animator animator;//人物的Animator组件
    private GameObject Hero;//人物

    private bool startToRun;

    float t = 0, w = 0;//赋初值

    private void Awake()
    {
        Hero = transform.Find("juggment").gameObject;
        animator = Hero.GetComponent<Animator>();
    }

    void FixedUpdate()
    {
        if (Input.GetMouseButtonDown(1))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            suc = Physics.Raycast(ray, out hit,1000);
            if(suc)
            {
                if(t<=0.01f)
                startToRun = true;
                animator.SetFloat("Blend", 1);//防止在奔跑状态转到默认状态途中发出行走指令,导致Blend的值恒定
                Hero.transform.localPosition = Vector3.zero;
                Hero.transform.localRotation = Quaternion.Euler(0, 0, 0);
                transform.LookAt(hit.point);
            }
        }
        if (suc)
        {
            Debug.DrawLine(transform.position, hit.point);
            transform.position = Vector3.MoveTowards(transform.position, hit.point, Time.fixedDeltaTime * 8);
        }

        if (Vector3.Distance( transform.position , hit.point)<=0.01f&&suc )
        {
            w = Mathf.Clamp(w -= Time.fixedDeltaTime*5, -1 ,0);//近似到达终点时,开始过渡到默认动画
            t = Mathf.InverseLerp(0, 1 , 1 + w);//求比例
            animator.SetFloat("Blend" , t);
            if (t <= 0.01f)
            {
                w = 0;
                t = 0;
                suc = false;
            }
        }
        else if(startToRun)
        {
            w = Mathf.Clamp(w += Time.fixedDeltaTime*10, 0, 1);
            t = Mathf.InverseLerp(0, 1, w);
            animator.SetFloat("Blend", t);
            if(t>=0.99f)
            {
                w = 0;
                t = 1;
                startToRun = false;
            }
        }

    }
}

总结与感悟:别眼高手低!别眼高手低!别眼高手低!

                        方法千千万,我的一定不是2最好的,希望各路大神给我更好的方案!

猜你喜欢

转载自blog.csdn.net/qq_15020543/article/details/83277904