在很多项目中,都有这样的场景就是鼠标点击一个位置,鼠标所控制的玩家就会移动到指定的位置处,还有就是在战斗过程中任务头上血条的UI跟随显示,今天就讲一下如何实现通过鼠标控制人物移动和人物头部血条的显示。
一、首先是搭建简易的3D场景
这里使用Terrain地形组件,安装官方资源之后,然后将对应的Environment导入到项目中:
设置地形参数,可以刷一些树木,草什么的 ,自行编辑就行 ,这里不做详细解释,场景如下图:
二、导入人物模型,添加相机跟随脚本
这里为了方便直接使用了官方提供的SmoothFollow脚本,创建一个新的相机用于渲染模型,在这个相机上添加SmoothFollow,如下图:
这里Target就是目标物体也就是,当前的角色模型
三、实现鼠标控制人物的移动:
首先创建一个脚本PlayerControl,这里主要就是通过射线检测,点击到地面的位置,计算角色的转向,然后沿着这个方向移动到指定位置 关于旋转的角度主要是通过点乘获得了目标位置对于玩家的朝向是背对着还是面对着,然后就是计算角度决定从那个方向旋转到目标方向:
if (Input.GetMouseButtonDown(0))
{
//获取从主相机发出的一条射线
Ray mRay = PlayerCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit mHit;
if (Physics.Raycast(mRay, out mHit))
{
if (mHit.collider.gameObject.name == "MyTerrain")
{
mTargetPos = mHit.point;
Vector3 posTem = mHit.point - transform.position;
float dot = Vector3.Dot(posTem.normalized, transform.right);
float angle = Vector3.Angle(posTem.normalized, transform.forward);
transform.Rotate(new Vector3(0, dot > 0 ? angle : -angle, 0));
}
if (Time.realtimeSinceStartup - clickTimer < 0.2f)
{
m_PlayerStastu = PlayerStastu.Run;
speed = 5;
}
else
{
m_PlayerStastu = PlayerStastu.Walk;
speed = 2;
}
clickTimer = Time.realtimeSinceStartup;
}
}
上面还通过鼠标的单机还是双击决定了角色的移动方式是行走还是奔跑,在这里锁定了角色的旋转方向就是只允许改变角色的y轴转向,然后就是角色的移动和动画的播放:
if (m_PlayerStastu == PlayerStastu.Walk || m_PlayerStastu == PlayerStastu.Run)
{
PlayAnimation();
//开始向指定方向移动
transform.Translate(Vector3.forward * speed * Time.deltaTime);
//计算和目标位置的距离
float targetDist = Vector3.Distance(mTargetPos, transform.position);
//当两者的距离小于0.1,停止移动
if (targetDist <= 0.1f)
{
m_PlayerStastu = PlayerStastu.Idle;
PlayAnimation();
}
}
四、实现血条的ui跟随角色移动:
拼接一个血条的ui,这里用的是ugui:
这里把ui的跟随代码 放大了LateUpdate中实现,LateUpdate主要是在update后执行的,在这之后再去确定ui的位置,在一定程度上可以放置ui的抖动,具体区别可自行百度:
void LateUpdate()
{
//处理ui 跟随人物移动
Vector3 screenPos = PlayerCamera.WorldToScreenPoint(transform.position);
Vector3 uiPos = UICamera.ScreenToWorldPoint(screenPos);
BloodUi.transform.localPosition = uiPos + new Vector3(0, 350, 0);
}
最后就是关于动画的播放,比较简单:
//播放动画
void PlayAnimation()
{
transform.GetComponent<Animation>().Play(m_PlayerStastu.ToString());
}
下面是控制角色移动的完整脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControl : MonoBehaviour
{
private Vector3 mTargetPos; //鼠标点击目标位置
public Camera PlayerCamera; //玩家相机
public Camera UICamera; //ui相机
public Transform BloodUi; //血条ui
private PlayerStastu m_PlayerStastu; //当前玩家状态
private float clickTimer; //记录上次点击时间
private float speed;
private enum PlayerStastu
{
Idle,
Walk,
Run,
}
void Start()
{
m_PlayerStastu = PlayerStastu.Idle;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
//获取从主相机发出的一条射线
Ray mRay = PlayerCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit mHit;
if (Physics.Raycast(mRay, out mHit))
{
if (mHit.collider.gameObject.name == "MyTerrain")
{
mTargetPos = mHit.point;
Vector3 posTem = mHit.point - transform.position;
float dot = Vector3.Dot(posTem.normalized, transform.right);
float angle = Vector3.Angle(posTem.normalized, transform.forward);
transform.Rotate(new Vector3(0, dot > 0 ? angle : -angle, 0));
}
if (Time.realtimeSinceStartup - clickTimer < 0.2f)
{
m_PlayerStastu = PlayerStastu.Run;
speed = 5;
}
else
{
m_PlayerStastu = PlayerStastu.Walk;
speed = 2;
}
clickTimer = Time.realtimeSinceStartup;
}
}
if (m_PlayerStastu == PlayerStastu.Walk || m_PlayerStastu == PlayerStastu.Run)
{
PlayAnimation();
//开始向指定方向移动
transform.Translate(Vector3.forward * speed * Time.deltaTime);
//计算和目标位置的距离
float targetDist = Vector3.Distance(mTargetPos, transform.position);
//当两者的距离小于0.1,停止移动
if (targetDist <= 0.1f)
{
m_PlayerStastu = PlayerStastu.Idle;
PlayAnimation();
}
}
}
void LateUpdate()
{
//处理ui 跟随人物移动
Vector3 screenPos = PlayerCamera.WorldToScreenPoint(transform.position);
Vector3 uiPos = UICamera.ScreenToWorldPoint(screenPos);
BloodUi.transform.localPosition = uiPos + new Vector3(0, 350, 0);
}
//播放动画
void PlayAnimation()
{
transform.GetComponent<Animation>().Play(m_PlayerStastu.ToString());
}
}
最后是实际运行效果:
想了解更多可以关注下方公众号,或者添加QQ群:879354767
工程地址:
链接:https://pan.baidu.com/s/1IAZ0I2idBicWVvKeHQFQNg
提取码:x9g0