改进版
using UnityEngine;
namespace script
{
public class PlayerInput : MonoBehaviour
{
protected float InputH;
protected float InputV;
//控制角色的速度
protected float InputSpeed;
protected bool InputRun;
protected bool InputJump;
//是否可移动
protected bool MoveAble;
// Use this for initialization
protected virtual void Start()
{
MoveAble = true;
InputJump = false;
}
// Update is called once per frame
protected virtual void Update()
{
//要在Update里检测,FixedUpdate可能会错过为GetKeyDown为true的帧
if (Input.GetKeyDown(KeyCode.Mouse0))
{
MoveAble = false;
}
InputH = Input.GetAxis("Horizontal");
InputV = Input.GetAxis("Vertical");
SquareToCircle();
InputSpeed = Mathf.Sqrt(InputH * InputH + InputV * InputV);
if (Input.GetKey(KeyCode.LeftShift))
{
InputRun = true;
}
else
{
InputRun = false;
}
if (Input.GetKeyDown(KeyCode.Space))
{
InputJump = true;
}
else if (Input.GetKeyUp(KeyCode.Space))
{
InputJump = false;
}
}
/**
* 直角坐标转圆形坐标
*/
private void SquareToCircle()
{
InputH = InputH * Mathf.Sqrt(1 - InputV * InputV / 2.0f);
InputV = InputV * Mathf.Sqrt(1 - InputH * InputH / 2.0f);
}
}
}
using UnityEngine;
using Random = UnityEngine.Random;
namespace script
{
/**
* 动画控制器
*/
public class AnimController : PlayerInput
{
protected bool isHit;
private bool isAttack;
private bool attackFlag;
private float time;
private int jumpBool;
private int speedFloat;
private int attackBool;
private float animSpeed;
protected Camera MainCamera;
private Animator animator;
protected virtual void Awake()
{
animator = GetComponent<Animator>();
}
// Use this for initialization
protected override void Start()
{
base.Start();
//获取动画变量的Hash值,提高效率
jumpBool = Animator.StringToHash("Jump");
speedFloat = Animator.StringToHash("Speed");
attackBool = Animator.StringToHash("Attack");
MainCamera = Camera.main;
time = 0;
MoveAble = true;
}
/**
* 播放等待动画
*/
private void PlayWaitAnim()
{
if (Input.anyKey)
{
time = 0;
}
else
{
time += Time.deltaTime;
//30秒后,随机播放等待动画
if (time > 30)
{
var animCode = Random.Range(1, 5);
animator.Play("WAIT0" + animCode, -1);
time = 0;
}
}
}
public void ClearSignalAttack()
{
MoveAble = true;
attackFlag = false;
animator.SetBool(attackBool,false);
}
/**
* 受到攻击动画播放结束回调
*/
public void OnOver()
{
isHit = false;
}
// Update is called once per frame
protected override void Update()
{
base.Update();
PlayWaitAnim();
//要在Update里检测,FixedUpdate可能会错过为GetKeyDown为true的帧
if (Input.GetKeyDown(KeyCode.Mouse0))
{
/*if (!isHit)
{
isHit = true;
if (Random.Range(0, 2) == 0)
{
animator.Play("DAMAGED00", -1);
}
else
{
animator.Play("DAMAGED01", -1);
}
}*/
attackFlag = true;
animator.Play("ATTACK",-1);
animator.SetBool(attackBool,true);
MoveAble = false;
}
animSpeed = InputRun ? InputSpeed * 2.0f : InputSpeed;
animator.SetFloat(speedFloat, Mathf.Lerp(animator.GetFloat(speedFloat), animSpeed, 0.2f));
animator.SetBool(jumpBool,InputJump);
}
}
}
using UnityEngine;
namespace script
{
/**
* 角色控制器
*/
public class ThirdPersonController : AnimController
{
//走动速度
public float walkSpeed = 1.0f;
//跑动速度
public float runSpeed = 5.0f;
public float gravity = 9.8f;
public float jumpSpeed = 10f;
//转向速度
public float turnSpeed = 5f;
public GameObject model;
private float speed;
private CharacterController characterController;
private Vector3 moveDirection;
private Transform camTrans;
private Vector3 camDirection;
private Vector3 forward;
protected override void Awake()
{
base.Awake();
characterController = GetComponent<CharacterController>();
}
// Use this for initialization
protected override void Start()
{
base.Start();
camTrans = MainCamera.transform;
}
// Update is called once per frame
protected override void Update()
{
base.Update();
//当起跳后,前进速度被保存,用于表现跳跃后的惯性前进
//所以moveDirection的速度应在if里
if (characterController.isGrounded)
{
//先判断是否前进,提高性能
if (MoveAble && InputSpeed > 0.1)
{
//以摄像机为参照系
camDirection = camTrans.forward * InputV + camTrans.right * InputH;
camDirection.y = 0;
camDirection.Normalize();
//角色转向摄像机的方向
forward = Vector3.Slerp(
transform.forward,
camDirection,
turnSpeed * Time.deltaTime);
transform.forward = forward;
moveDirection.Set(forward.x, 0, forward.z);
speed = InputRun ? runSpeed : walkSpeed;
//向角色的前方前进,转向更加自然
}
else
{
speed = 0;
}
moveDirection *= speed;
if (InputJump)
{
moveDirection.y = jumpSpeed;
}
}
// 重力计算
moveDirection.y = moveDirection.y - (gravity * Time.deltaTime);
// 移动角色
characterController.Move(moveDirection * Time.deltaTime);
}
}
}
using UnityEngine;
namespace script
{
public class MoveCamera : MonoBehaviour
{
//观察目标
public Transform target;
//观察距离
public float distance = 2f;
//视角x轴旋转速度
public float speedX = 24;
//视角y轴旋转速度
public float speedY = 12;
//旋转角度限制
public float maxLimitY = 65;
public float minLimitY = -75;
//鼠标缩放距离限制
public float maxDistance = 10;
public float minDistance = 1.5F;
//鼠标缩放速率
public float zoomSpeed = 2F;
//旋转角度
private float mX = 0.0F;
private float mY = 0.0F;
//控制鼠标的显示
public bool lockCursor = true;
private Quaternion mRotation;
void Start()
{
//初始化旋转角度
Vector3 angles = transform.eulerAngles;
mX = angles.x;
mY = angles.y;
if (target == null)
{
//自动查找以player为标签的对象
GameObject player = GameObject.FindGameObjectWithTag("Player");
if (player != null)
{
target = player.transform;
}
else
{
//禁用脚本
enabled = false;
}
}
speedX *= 0.1f;
speedY *= 0.1f;
if (lockCursor)
{
Cursor.visible = false;
}
}
void Update()
{
//获取鼠标输入
mX += Input.GetAxis("Mouse X") * speedX;
mY -= Input.GetAxis("Mouse Y") * speedY;
mX = ClampAngle(mX);
//范围限制
mY = Mathf.Clamp(mY, minLimitY, maxLimitY);
//计算旋转
//我们可以通过Quaternion.Euler()方法将一个Vector3类型的值转化为一个四元数
//,进而通过修改Transform.Rotation来实现相同的目的
mRotation = Quaternion.Euler(mY, mX, 0);
//设置相机的方向
//不建议设置插值,应该立即更新
transform.rotation = mRotation;
//鼠标滚轮缩放
distance -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
distance = Mathf.Clamp(distance, minDistance, maxDistance);
//重新计算位置,设置相机位置
transform.position = mRotation * (new Vector3(0, 1, -distance)) + target.position;
}
//角度限制
private float ClampAngle(float angle)
{
if (angle < 0) angle += 360;
if (angle > 360) angle -= 360;
return angle;
}
}
}
未改进版
自由旋转,跟随角色,距离缩放
不建议使用差值,使用差值会导致快速旋转时镜头到角色的距离发生明显改变
using UnityEngine;
public class MoveCamera : MonoBehaviour
{
//观察目标
public Transform target;
//观察距离
public float distance = 2f;
//视角x轴旋转速度
public float speedX = 24;
//视角y轴旋转速度
public float speedY = 12;
//旋转角度限制
public float maxLimitY = 65;
public float minLimitY = -75;
//鼠标缩放距离限制
public float maxDistance = 10;
public float minDistance = 1.5F;
//鼠标缩放速率
public float zoomSpeed = 2F;
//旋转角度
private float mX = 0.0F;
private float mY = 0.0F;
//是否启用差值
public bool isNeedDamping = false;
//平滑度
public float damping = 10F;
//控制鼠标的显示
public bool lockCursor = true;
private Quaternion mRotation;
void Start()
{
//初始化旋转角度
Vector3 angles = transform.eulerAngles;
mX = angles.x;
mY = angles.y;
if (target == null)
{
//自动查找以player为标签的对象
GameObject player = GameObject.FindGameObjectWithTag("Player");
if (player != null)
{
target = player.transform;
}
else
{
//禁用脚本
enabled = false;
}
}
speedX *= 0.1f;
speedY *= 0.1f;
if (lockCursor)
{
Cursor.visible = false;
}
}
void LateUpdate()
{
//获取鼠标输入
mX += Input.GetAxis("Mouse X") * speedX;
mY -= Input.GetAxis("Mouse Y") * speedY;
mX = ClampAngle(mX);
//范围限制
mY = Mathf.Clamp(mY, minLimitY, maxLimitY);
//计算旋转
//我们可以通过Quaternion.Euler()方法将一个Vector3类型的值转化为一个四元数
//,进而通过修改Transform.Rotation来实现相同的目的
mRotation = Quaternion.Euler(mY, mX, 0);
//设置相机的方向
//根据是否插值采取不同的角度计算方式
if (isNeedDamping)
{
transform.rotation = Quaternion.Lerp(
transform.rotation, mRotation, Time.deltaTime * damping);
}
else
{
transform.rotation = mRotation;
}
//鼠标滚轮缩放
distance -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
distance = Mathf.Clamp(distance, minDistance, maxDistance);
//重新计算位置
Vector3 mPosition = mRotation * (new Vector3(0, 1, -distance)) + target.position;
//设置相机位置
if (isNeedDamping)
{
transform.position = Vector3.Lerp(transform.position, mPosition, Time.deltaTime * damping);
}
else
{
transform.position = mPosition;
}
}
//角度限制
private float ClampAngle(float angle)
{
if (angle < 0) angle += 360;
if (angle > 360) angle -= 360;
return angle;
}
}
跑、走、停、跳
using UnityEngine;
using Random = UnityEngine.Random;
/**
* 动画控制器
*/
public class AnimController : MonoBehaviour
{
protected float inputH;
protected float inputV;
//用来控制动画状态机的走、跑、停
protected int animSpeed;
private float time;
private int jumpBool;
private int speedInt;
private bool isHit;
protected Camera mainCamera;
private Animator animator;
// Use this for initialization
protected virtual void Start()
{
animator = GetComponent<Animator>();
//获取动画变量的Hash值,提高效率
jumpBool = Animator.StringToHash("Jump");
speedInt = Animator.StringToHash("Speed");
mainCamera = Camera.main;
time = 0;
}
/**
* 播放等待动画
*/
private void PlayWaitAnim()
{
if (Input.anyKey)
{
time = 0;
}
else
{
time += Time.deltaTime;
//30秒后,随机播放等待动画
if (time > 30)
{
var animCode = Random.Range(1, 5);
animator.Play("WAIT0" + animCode, -1);
time = 0;
}
}
}
/**
* 受到攻击动画播放结束回调
*/
public void OnOver()
{
isHit = false;
}
// Update is called once per frame
protected virtual void Update()
{
PlayWaitAnim();
//要在Update里检测,FixedUpdate可能会错过为GetKeyDown为true的帧
if (Input.GetKeyDown(KeyCode.Mouse0))
{
if (!isHit)
{
isHit = true;
if (Random.Range(0, 2) == 0)
{
animator.Play("DAMAGED00", -1);
}
else
{
animator.Play("DAMAGED01", -1);
}
}
}
inputH = Input.GetAxis("Horizontal");
inputV = Input.GetAxis("Vertical");
animSpeed = IsMove() ? 1 : 0;
if (animSpeed == 1 && Input.GetKey(KeyCode.LeftShift))
{
animSpeed = 2;
}
animator.SetInteger(speedInt, animSpeed);
if (Input.GetKeyDown(KeyCode.Space))
{
animator.SetBool(jumpBool, true);
}else if (Input.GetKeyUp(KeyCode.Space))
{
animator.SetBool(jumpBool, false);
}
}
/**
* 是否正在移动
*/
private bool IsMove()
{
return !isHit && (inputH > 0.1 || inputV > 0.1 || inputH < -0.1 || inputV < -0.1);
}
}
镜头控制转向
using System;
using UnityEngine;
/**
* 角色控制器
*/
public class ThirdPersonController : AnimController
{
//走动速度
public float walkSpeed = 1.0f;
//跑动速度
public float runSpeed = 5.0f;
//转向速度
public float turnSpeed = 1.5f;
private float speed;
private CharacterController characterController;
private Rigidbody rig;
// Use this for initialization
protected override void Start()
{
base.Start();
characterController = GetComponent<CharacterController>();
speed = walkSpeed;
rig = GetComponent<Rigidbody>();
}
// Update is called once per frame
protected override void Update()
{
base.Update();
//先判断是否前进,提高性能
if (animSpeed > 0)
{
Vector3 moveDirection = new Vector3(inputH, 0, inputV);
//以摄像机为参照系
moveDirection = mainCamera.transform.TransformDirection(moveDirection);
moveDirection.y = 0;
//角色转向摄像机的方向
this.transform.rotation = Quaternion.Slerp(
this.transform.rotation,
Quaternion.LookRotation(moveDirection),
turnSpeed * Time.deltaTime);
speed = animSpeed == 1 ? walkSpeed : runSpeed;
//向角色的前方前进,转向更加自然
characterController.SimpleMove(
transform.TransformDirection(Vector3.forward) * speed);
}
}
}