版权声明:转载请注明出处!不注明也无所谓,嘿嘿。 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;
}
}
}
}