刚开始学习u3d,u3d自带的ThirdPersonController.js实在是看得不太懂,而且动作实在太少了,想做一个动作类游戏都做不成。
今天初步把它改成了cs版本,并随便加了几个动作,以便后期使用。
每天奋斗一点点
.
using UnityEngine;
using System.Collections;
public class ThirdPersonControl : MonoBehaviour {
#region 动作片段
public AnimationClip idleAnimation;
public AnimationClip walkAnimation;
public AnimationClip runAnimation;
public AnimationClip jumpPoseAnimation;
public AnimationClip jumpFallAnimation;
public AnimationClip kickAnimation;
public AnimationClip utimateAnimation;
private Animation _animation;
#endregion
#region 动作片段枚举值
enum CharacterState
{
Idle = 0,
Walking = 1,
Trotting = 2,
Running = 3,
Jumping = 4,
Falling = 5,
Kicking = 6,
Utimate = 7
}
#endregion
#region 最大限速
public float walkMaxAnimationSpeed = 0.75f;
public float trotMaxAnimationSpeed = 1.0f;
public float runMaxAnimationSpeed = 1.0f;
public float jumpAnimationSpeed = 1.15f;
public float landAnimationSpeed = 1.0f;
public float kickMaxAnimationSpeed = 0.8f;
#endregion
//判断游戏是否开始
public static int jug = 0;
//判断角色状态
private CharacterState _characterState;
#region 角色在做什么
// Are we jumping? (Initiated with jump button and not grounded yet)
//是否正在跳跃
public bool jumping = false;
private bool jumpingReachedApex = false;
//是否正在踢人
public bool kicking = false;
//是否正在放大
public bool utimating = false;
//各种状态
public bool slow = false;
#endregion
#region 记录动作开始时间以及各种参数
// When did the user start walking (Used for going into trot after a while)
//走路开始时间,一段时间后进入快跑状态
private float walkTimeStart = 0.0f;
// Last time the jump button was clicked down
//最后一次按“跳跃按键的时间”
private float lastJumpButtonTime = -10.0f;
//跳
private float lastJumpTime = -1.0f;
//踢
private float lastKickTime = -1.0f;
//绝技
private float lastUtimateTime = -0.1f;
// the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)
//记录最后一次跳跃时的高度(高度过高会受伤之类的)
private float lastJumpStartHeight = 0.0f;
//绝技
private float lastUtimateStartHeight = 0.0f;
//落地
private float lastGroundedTime = 0.0f;
//跳跃参数
private float jumpRepeatTime = 0.05f;
private float jumpTimeout = 0.15f;
private float groundedTimeout = 0.25f;
//减速时间
public float slowTime=0.0f;
#endregion
#region 角色基本属性,可以外部修改
// The speed when walking
public float walkSpeed = 2.0f;
// after trotAfterSeconds of walking we trot with trotSpeed
public float trotSpeed = 4.0f;
// when pressing "Fire3" button (cmd) we start running
public float runSpeed = 6.0f;
public float kickSpeed = 3.0f;
//????
public float inAirControlAcceleration = 3.0f;
// How high do we jump when pressing jump and letting go immediately
public float jumpHeight = 0.5f;
// The gravity for the character
public float gravity = 20.0f;
// The gravity in controlled descent mode
public float speedSmoothing = 10.0f;
public float rotateSpeed = 500.0f;
public float trotAfterSeconds = 3.0f;
//可跳与否
public bool canJump = true;
#endregion
#region 各种私有变量
// The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.
private float lockCameraTimer = 0.0f;
// The current move direction in x-z
private Vector3 moveDirection = Vector3.zero;
// The current vertical speed
private float verticalSpeed = 0.0f;
// The current x-z move speed
private float moveSpeed = 0.0f;
// The last collision flags returned from controller.Move
private CollisionFlags collisionFlags;
// Are we moving backwards (This locks the camera to not do a 180 degree spin)
//是否往回走
private bool movingBack = false;
// Is the user pressing any keys?
private bool isMoving = false;
private Vector3 inAirVelocity = Vector3.zero;
//是否可以控制
private bool isControllable = true;
#endregion
void Awake ()
{
moveDirection = transform.TransformDirection(Vector3.forward);
_animation = gameObject.GetComponent<Animation>();
//若没有animation组件则报错
if(!_animation)
Debug.Log("The character you would like to control doesn't have animations. Moving her might look weird.");
//检查各个Animation是否都存在对应动作
if(!idleAnimation) {
_animation = null;
Debug.Log("No idle animation found. Turning off animations.");
}
if(!walkAnimation) {
_animation = null;
Debug.Log("No walk animation found. Turning off animations.");
}
if(!runAnimation) {
_animation = null;
Debug.Log("No run animation found. Turning off animations.");
}
if(!jumpPoseAnimation && canJump) {
_animation = null;
Debug.Log("No jump animation found and the character has canJump enabled. Turning off animations.");
}
if(!jumpFallAnimation) {
_animation = null;
Debug.Log("No fall animation found and the character has canJump enabled. Turning off animations.");
}
if(!kickAnimation) {
_animation = null;
Debug.Log("No kick animation found. Turning off animations.");
}
if(!utimateAnimation) {
_animation = null;
Debug.Log("No utimate animation found. Turning off animations.");
}
}
void UpdateSmoothedMovementDirection ()
{
//找到主摄像机的位置
Transform cameraTransform = Camera.main.transform;
//与操作,返回值为bool型,1为在地上,0为在空中
bool grounded = IsGrounded();
// Forward vector relative to the camera along the x-z plane
//找到摄像机向前一步的向量,并把向量中的y置0
Vector3 forward = cameraTransform.TransformDirection(Vector3.forward);
forward.y = 0;
forward = forward.normalized;
// Right vector relative to the camera
// Always orthogonal to the forward vector
//跟着摄像机的移动方向往右走
Vector3 right = new Vector3(forward.z, 0, -forward.x);
//获得水平移动和垂直移动的float值
float v = Input.GetAxisRaw("Vertical");
float h = Input.GetAxisRaw("Horizontal");
// Are we moving backwards or looking backwards
//若垂直移动距离太小,movingBack值置为true,意思是已进行后移
if (v < -0.2)
movingBack = true;
else
movingBack = false;
//wasMoving存isMoving,表示是否正在移动
bool wasMoving = isMoving;
//或操作,若水平移动或者垂直移动的绝对值>0.1,则返回1,表示正在移动0
isMoving = Mathf.Abs (h) > 0.1 || Mathf.Abs (v) > 0.1;
// Target direction relative to the camera
//
Vector3 targetDirection = h * right + v * forward;
// Grounded controls
//若在地上
if (grounded && !kicking)
{
// Lock camera for short period when transitioning moving & standing still
//控制对应的ThirdPerson Camera 本游戏用不到
lockCameraTimer += Time.deltaTime;
if (isMoving != wasMoving)
lockCameraTimer = 0.0f;
// We store speed and direction seperately,
// so that when the character stands still we still have a valid forward direction
// moveDirection is always normalized, and we only update it if there is user input.
if (targetDirection != Vector3.zero)
{
// If we are really slow, just snap to the target direction
if (moveSpeed < walkSpeed * 0.9 && grounded)
{
moveDirection = targetDirection.normalized;
}
// Otherwise smoothly turn towards it
else
{
moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
moveDirection = moveDirection.normalized;
}
}
// Smooth the speed based on the current target direction
float curSmooth = speedSmoothing * Time.deltaTime;
// Choose target speed
//* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f);
_characterState = CharacterState.Idle;
// Pick speed modifier
if (Input.GetKey (KeyCode.LeftShift) || Input.GetKey (KeyCode.RightShift))
{
targetSpeed *= runSpeed;
_characterState = CharacterState.Running;
}
else if (Time.time - trotAfterSeconds > walkTimeStart)
{
targetSpeed *= trotSpeed;
_characterState = CharacterState.Trotting;
}
else
{
targetSpeed *= walkSpeed;
_characterState = CharacterState.Walking;
}
moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);
// Reset walk time start when we slow down
if (moveSpeed < walkSpeed * 0.3)
walkTimeStart = Time.time;
}
// In air controls
else
{
// Lock camera while in air
if (jumping)
lockCameraTimer = 0.0f;
if (isMoving)
inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration;
}
}
void ApplyJumping ()
{
// Prevent jumping too fast after each other
//设置一个时间间隔,这里为Time.time,在这间隔内不能连续跳跃
if (lastJumpTime + jumpRepeatTime > Time.time)
return;
if (IsGrounded()&&!utimating&&!kicking) {
// Jump
// - Only when pressing the button down
// - With a timeout so you can press the button slightly before landing
//若可以跳跃,则跳
if (canJump && Time.time < lastJumpButtonTime + jumpTimeout) {
verticalSpeed = CalculateJumpVerticalSpeed (jumpHeight);
SendMessage("DidJump", SendMessageOptions.DontRequireReceiver);
}
}
}
void ApplyGravity ()
{
//若角色处于可控状态
if (isControllable&&!utimating) // don't move player at all if not controllable.
{
// Apply gravity
var jumpButton = Input.GetButton("Jump");
// When we reach the apex of the jump we send out a message
//若jumping、并没有达到跳跃最高点、垂直速度<0
if (jumping && !jumpingReachedApex && verticalSpeed <= 0.0)
{
//把角色已到达最高点置为真
jumpingReachedApex = true;
//执行DidJumpReachApex,这里没有
SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
}
//若已到达地面
if (IsGrounded ())
//垂直速度置0
verticalSpeed = 0.0f;
else
//若没到达地面,设置下落速度
verticalSpeed -= gravity * Time.deltaTime;
}
}
void ApplyKicking()
{
if (lastKickTime + 0.5 > Time.time)
return;
if (IsGrounded()&&!kicking)
{
SendMessage("DidKick", SendMessageOptions.DontRequireReceiver);
}
}
void ApplyUtimating()
{
if (lastUtimateTime + 0.5 > Time.time)
return;
if(!IsGrounded())
{
SendMessage("DidUtimate", SendMessageOptions.DontRequireReceiver);
}
}
float CalculateJumpVerticalSpeed (float targetJumpHeight)
{
// From the jump height and gravity we deduce the upwards speed
// for the character to reach at the apex.
return Mathf.Sqrt(2 * targetJumpHeight * gravity);
}
void DidJump ()
{
jumping = true;
jumpingReachedApex = false;
lastJumpTime = Time.time;
lastJumpStartHeight = transform.position.y;
lastJumpButtonTime = -10;
_characterState = CharacterState.Jumping;
}
void DidKick()
{
kicking = true;
lastKickTime = Time.time;
_characterState = CharacterState.Kicking;
}
void DidUtimate()
{
utimating=true;
lastUtimateTime = Time.time;
lastUtimateStartHeight = transform.position.y;
_characterState = CharacterState.Utimate;
}
void Update() {
if(jug==1){
//如果不能控制,则重置输入轴
if (!isControllable)
{
// kill all inputs if not controllable.
Input.ResetInputAxes();
}
//如果按下跳(就是空格)键,把最后起跳时间记录下来
if (Input.GetButtonDown ("Jump"))
{
lastJumpButtonTime = Time.time;
}
//这东西是对对应ThirdPersonCamera的摄像机的位置进行修正,本游戏用不到
UpdateSmoothedMovementDirection();
// Apply gravity
// - extra power jump modifies gravity
// - controlledDescent mode modifies gravity
ApplyGravity ();
// Apply jumping logic
ApplyJumping ();
if(Input.GetKeyDown(KeyCode.K))
{
ApplyUtimating();
}
if(Input.GetKeyDown(KeyCode.J))
{
ApplyKicking();
}
// Calculate actual motion
//计算角色的移动向量
var movement = moveDirection * moveSpeed + new Vector3 (0, verticalSpeed, 0) + inAirVelocity;
movement *= Time.deltaTime;
// Move the controller
//移动角色
CharacterController controller = gameObject.GetComponent<CharacterController>();
collisionFlags = controller.Move(movement);
// ANIMATION sector
//若每一个动作片段都存在
if(_animation) {
//若角色的状态处于跳跃状态
if(_characterState == CharacterState.Jumping)
{
//若没到达跳跃顶峰
if(!jumpingReachedApex) {
//执行跳跃动作
_animation[jumpPoseAnimation.name].speed = jumpAnimationSpeed;
//重复执行这一动作直到结束
_animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpPoseAnimation.name);
} else {
//若已到达顶峰
//执行下落动作
_animation[jumpFallAnimation.name].speed = -landAnimationSpeed;
//重复执行这一动作直到结束
_animation[jumpFallAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpFallAnimation.name);
}
}
else if(_characterState == CharacterState.Kicking)
{
//若处于踢人状态
if(Time.time - lastKickTime<0.8)
{
_animation[kickAnimation.name].speed = kickMaxAnimationSpeed;
_animation[kickAnimation.name].wrapMode = WrapMode.Loop;
_animation.CrossFade(kickAnimation.name);
}else
{
//lastKickTime = Time.time;
kicking = false;
}
}
else if(_characterState == CharacterState.Utimate)
{
//若处于放大招状态
if(Time.time - lastUtimateTime<0.5)
{
//_animation[utimateAnimation.name].speed = jumpAnimationSpeed;
Vector3 newY = transform.position;
newY.y = lastUtimateStartHeight;
transform.position = newY;
_animation[utimateAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(utimateAnimation.name);
verticalSpeed -= gravity * Time.deltaTime*0.5f;
}else{
utimating=false;
jumpingReachedApex = true;
_characterState = CharacterState.Jumping;
}
}
else
{
//若不处于跳跃状态
//若角色的运行向量开方小于0.1,执行Idle动作
if(controller.velocity.sqrMagnitude < 0.1) {
_animation.CrossFade(idleAnimation.name);
}
else
{
//若角色的运行向量开方大于0.1
//若角色处于奔跑状态
if(_characterState == CharacterState.Running) {
_animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, runMaxAnimationSpeed);
_animation.CrossFade(runAnimation.name);
}
//若处于快步走状态
else if(_characterState == CharacterState.Trotting) {
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, trotMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
}
//若处于走路状态
else if(_characterState == CharacterState.Walking) {
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, walkMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
}
}
}
}
// ANIMATION sector
// Set rotation to the move direction
if (IsGrounded())
{
transform.rotation = Quaternion.LookRotation(moveDirection);
}
else
{
var xzMove = movement;
xzMove.y = 0;
if (xzMove.sqrMagnitude > 0.001)
{
transform.rotation = Quaternion.LookRotation(xzMove);
}
}
// We are in jump mode but just became grounded
if (IsGrounded())
{
lastGroundedTime = Time.time;
inAirVelocity = Vector3.zero;
if (jumping)
{
jumping = false;
SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);
}
}
}
}
void OnControllerColliderHit (ControllerColliderHit hit )
{
// Debug.DrawRay(hit.point, hit.normal);
if (hit.moveDirection.y > 0.01)
return;
}
float GetSpeed () {
return moveSpeed;
}
bool IsJumping () {
return jumping;
}
bool IsGrounded () {
return (collisionFlags & CollisionFlags.CollidedBelow) != 0;
}
Vector3 GetDirection () {
return moveDirection;
}
bool IsMovingBackwards () {
return movingBack;
}
float GetLockCameraTimer ()
{
return lockCameraTimer;
}
bool IsMoving ()
{
return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) > 0.5;
}
bool HasJumpReachedApex ()
{
return jumpingReachedApex;
}
bool IsGroundedWithTimeout ()
{
return lastGroundedTime + groundedTimeout > Time.time;
}
void Reset ()
{
gameObject.tag = "Player";
}
}
.
存此记录我的游戏开发过程。