人物添加刚体后,关闭动画影响
简单的人物移动逻辑
简单的动画
添加移动脚本
public class PlayerMovement : MonoBehaviour
{
private float turnspeed;//人物旋转速度
Animator m_animator;
Rigidbody rb;
Vector3 m_movement;
Quaternion m_rotation = Quaternion.identity;
void Start() //第一帧执行
{
m_animator = GetComponent<Animator>();
rb = GetComponent<Rigidbody>();
turnspeed = 20;
}
// Update is called once per frame
void Update() //每帧执行
{
}
private void FixedUpdate()
{
//获取水平垂直的轴值
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
//设置人物移动方向
m_movement.Set(horizontal, 0, vertical);
//防止双方向同时按,轴值大于1
m_movement.Normalize();
//判断是否移动
bool hasHorizontalInput = !Mathf.Approximately(horizontal, 0);//Approximately比较两个浮点数是否相近
bool hasVerticalInput = !Mathf.Approximately(vertical, 0);
//定义变量判断移动动画是否播放
bool isWalking = hasHorizontalInput || hasVerticalInput;
m_animator.SetBool("IsWalking", isWalking);
//人物视角朝向的过渡
Vector3 designForward = Vector3.RotateTowards(transform.forward, m_movement, turnspeed * Time.deltaTime, 0f);
m_rotation = Quaternion.LookRotation(designForward);
}
private void OnAnimatorMove() //人物的朝向和移动
{
//当前位置向量+目标位置向量
rb.MovePosition(rb.position + m_movement * m_animator.deltaPosition.magnitude);
rb.MoveRotation(m_rotation);
}
}
相机固定距离跟随(脚本或者虚拟相机实现都可)
1.MainCamera挂载脚本
public class CameraFollow : MonoBehaviour
{
private Transform m_FollowTarget;
Vector3 offset; //差值
void Start()
{
m_FollowTarget = GameObject.Find("JohnLemon").transform;
offset = transform.position - m_FollowTarget.position;
}
// Update is called once per frame
void Update()
{
transform.position = offset + m_FollowTarget.position;
}
}
2.虚拟相机
添加跟随对象,调整一下相机角度、camera distance,Aim改为do nothing.
制作游戏结束UI界面
Canvas -> image
平铺图片充满画布
GameEnding.cs
public class GameEnding : MonoBehaviour
{
//游戏胜利时淡入淡出的时间
public float fadeDuration = 1.0f;
//UI显示时间
public float displayDuration = 1.0f;
//游戏人物
public GameObject Player;
//画布背景
public CanvasGroup ExitBK;
//游戏胜利时的bool值
bool IsExit;
//定义计时器,图片渐变显示
private float timer = 0 ;
private void OnTriggerEnter(Collider other)
{
if(other.gameObject == Player)
{
//检测到玩家
//游戏胜利
IsExit = true;
}
}
// Update is called once per frame
void Update()
{
if (IsExit)
{
//显示游戏胜利图片的方法
EndLevel();
}
}
void EndLevel()
{
timer += Time.deltaTime;
ExitBK.alpha = timer / fadeDuration;
if(timer > fadeDuration + displayDuration) //游戏退出
{
Application.Quit();
}
}
}
敌人
静态敌人
添加在敌人视野区的脚本
public class Observer : MonoBehaviour
{
//游戏角色
//public Transform Player;
public Transform Player;
public GameEnding gameEnding;
//游戏玩家是否进入到扫描棒的视线范围
bool IsInRange = false;//是否扫描到玩家
private void OnTriggerEnter(Collider other)
{
if(other.gameObject == Player.gameObject)
{
IsInRange = true;
}
}
private void OnTriggerExit(Collider other)
{
if(other.gameObject == Player.gameObject)
{
IsInRange = false;
}
}
private void Start()
{
}
private void Update()
{
if (IsInRange) //玩家进入敌人视野区域
{
Vector3 dir = Player.position - transform.position + Vector3.up; //v3.up是单位向上的长度
//射线检测,判断是否扫描到玩家
Ray ray = new Ray(transform.position, dir);//从敌人这里创建射线
RaycastHit hit;//存储返回结果
if(Physics.Raycast(ray,out hit))
{
if(hit.collider.transform == Player)
{
//宣告游戏失败
gameEnding.Caught();
}
}
}
}
}
动态敌人
烘焙完地形后,添加Nav Mesh Agent组件
同样给敌人添加视野区
使用Nav Mesh添加巡逻路径
添加脚本
public class WayPointsPatrol : MonoBehaviour
{
private NavMeshAgent m_Agent;
public Transform[] waypoints;
//当前巡逻终点
int m_currentpointIndex;
// Start is called before the first frame update
void Start()
{
m_Agent = GetComponent<NavMeshAgent>();
//从起点到达第一个巡逻点
m_Agent.SetDestination(waypoints[0].position);
}
// Update is called once per frame
void Update()
{
if(m_Agent.remainingDistance < m_Agent.stoppingDistance) //到达目标点
{
//切换目标点
m_currentpointIndex = (m_currentpointIndex+1)%waypoints.Length; // 循环队列
m_Agent.SetDestination(waypoints[m_currentpointIndex].position);
}
}
}
音乐和音效
//添加音频组件
public AudioSource[] audio; //1.胜利 2.失败
bool audioIsPlaying; //播放一次
void Update()
{
if (IsExit)//游戏胜利
{
//显示游戏胜利图片的方法
EndLevel(ExitBK,false);
if (!audioIsPlaying)
{
audio[0].Play();
audioIsPlaying = true;
}
}else if (IsFail)//游戏失败
{
EndLevel(FailBK, true);
if(!audioIsPlaying)
{
audio[1].Play();
audioIsPlaying = true;
}
}
}