Fix my unity3D code to XENKO


#1

Played “World of Warcraft” friends all know, “World of Warcraft” role controller is very good, Unity3D standard package comes with a third person and first-person character controller, but the feeling of the top a lot worse, the following Third-person character controller to imitate the “World of Warcraft,” I hope you like it.
As usual, let’s take a look at the final effect, we can control the role of the keyboard and mouse rotation, movement, vision closer and so on, as shown:

The third person role controller main class UPlayerController.cs, the code is as follows:

indent preformatted text by 4 spaces

using UnityEngine;
using System.Collections;

public class UPlayerController : MonoBehaviour
{
///


/// 待机动画
///

public AnimationClip idleClip;

/// <summary>
/// 行走动画
/// </summary>
public AnimationClip walkClip;

/// <summary>
/// 跑步动画
/// </summary>
public AnimationClip runClip;

/// <summary>
/// 跳跃动画
/// </summary>
public AnimationClip jumpClip;

/// <summary>
/// 后退动画
/// </summary>
public AnimationClip retreatClip;

/// <summary>
/// 跑步移动速度
/// </summary>
public float runSpeed = 6.0f;
 
/// <summary>
/// 行走移动速度
/// </summary>
public float walkSpeed = 3.0f;
 
/// <summary>
/// 后退移动速度
/// </summary>
public float retreatSpeed = 2.0f;
 
/// <summary>
/// 移动速度
/// </summary>
public float speed = 0f;

/// <summary>
/// 摄像机对象
/// </summary>
public Transform cameraTransform;

/// <summary>
/// 角度头部对象
/// </summary>
public Transform headTransform;

/// <summary>
/// 摄像机偏离距离
/// </summary>
public float cameraDistance = 5f;

/// <summary>
/// 摄像机最近视角
/// </summary>
public float cameraZoomNear = 0.01f;

/// <summary>
/// 摄像机最远视角
/// </summary>
public float cameraZoomFar = 30.0f;

/// <summary>
/// 鼠标移动 X 坐标轴
/// </summary>
public float mouseXAxis = 15.0f;

/// <summary>
/// 鼠标移动 Y 坐标轴
/// </summary>
public float mouseYAxis = 15.0f;

/// <summary>
/// 鼠标滚轮速率
/// </summary>
public float mouseWheelVelocity = 3.0f;

/// <summary>
/// 跳起速率
/// </summary>
public float jumpVelocity = 15f;

/// <summary>
/// 下落速率
/// </summary>
public float dropVelocity = 10f;

/// <summary>
/// 摄像机位置修正
/// </summary>
public float cameraReviseDistance = 1.0f;

/// <summary>
/// 最小位置
/// </summary>
public float cameraClampMin = -70f;

/// <summary>
/// 最大位置
/// </summary>
public float cameraClampMax = 90f;

/// <summary>
/// 偏移角度
/// </summary>
public float offsetAngle = 90f;
 
/// <summary>
/// 移动向量,通过计算得来
/// </summary>
protected Vector3 moveDirection;

/// <summary>
/// 垂直速率
/// </summary>
protected float verticalVelocity;

/// <summary>
/// 屏幕鼠标 X 坐标
/// </summary>
protected float mouseX;

/// <summary>
/// 屏幕鼠标 Y 坐标
/// </summary>
protected float mouseY;

/// <summary>
/// 前一次鼠标 X 坐标
/// </summary>
protected float prevMouseX;

/// <summary>
/// 前一次鼠标 Y 坐标
/// </summary>
protected float prevMouseY;

/// <summary>
/// 前一次旋转
/// </summary>
protected Quaternion prevQuaternion;

/// <summary>
/// 前一次朝向
/// </summary>
protected Vector3 prevForward;

/// <summary>
/// 是否正在起跳
/// </summary>
protected bool isJumping;

/// <summary>
/// 插值转向变量
/// </summary>
protected float mouseXVelocity;

/// <summary>
/// 插值跳起变量
/// </summary>
protected float currentJumpVelocity;

/// <summary>
/// 角色当前状态
/// </summary>
protected string roleActionEnum;

/// <summary>
/// Q、E 移动向量
/// </summary>
protected float horizontalQEDirection;

/// <summary>
/// 水平方向向量
/// </summary>
protected float horizontalDirection;

/// <summary>
/// 垂直方向向量
/// </summary>
protected float verticalDirection;

/// <summary>
/// 鼠标 X 属性
/// </summary>
protected float mouseXDirection;

/// <summary>
/// 鼠标 Y 属性
/// </summary>
protected float mouseYDirection;

/// <summary>
/// 鼠标滚轮属性
/// </summary>
protected float mouseScrollWheelDirection;

/// <summary>
/// 水平移动数据
/// </summary>
protected float horizontalValue;

/// <summary>
/// 垂直移动数据
/// </summary>
protected float verticalValue;

/// <summary>
/// 跳起状态
/// </summary>
protected bool jumpStatus;

/// <summary>
/// 鼠标左键按下状态
/// </summary>
protected bool buttonDownLeftStatus;

/// <summary>
/// 鼠标左键弹起状态
/// </summary>
protected bool buttonUpLeftStatus;

/// <summary>
/// 鼠标左键状态
/// </summary>
protected bool buttonLeftStatus;

/// <summary>
/// 鼠标右键状态
/// </summary>
protected bool buttonRightStatus;

/// <summary>
/// 左边 Shift 状态
/// </summary>
protected bool shiftLeftStatus;
 
/// <summary>
/// 右边 Shift 状态
/// </summary>
protected bool shiftRightStatus;

/// <summary>
/// 角色控制器
/// </summary>
private CharacterController characterController;

/// <summary>
/// 动画
/// </summary>
private Animation animation;

void Awake ()
{
    if (this.cameraTransform == null && Camera.main != null) this.cameraTransform = Camera.main.transform;
    if (this.cameraTransform == null) return;

    this.characterController = this.GetComponentInChildren<CharacterController> ();
    this.animation = this.GetComponentInChildren<Animation> ();

    this.cameraTransform.parent = this.headTransform;
    this.cameraTransform.localPosition = Vector3.zero;
     
    this.cameraTransform.position = this.transform.position;

    this.verticalVelocity = 0f;

    this.animation.CrossFade (this.idleClip.name);
}

/// <summary>
/// 初始化输入数据
/// </summary>
protected virtual void InitInputData()
{
    if (this.cameraTransform == null) return;

    this.horizontalQEDirection = 0f;
    this.horizontalDirection = Input.GetAxisRaw ("Horizontal");
    this.verticalDirection = Input.GetAxisRaw ("Vertical");
    this.mouseXDirection = Input.GetAxis ("Mouse X") * this.mouseXAxis;
    this.mouseYDirection = Input.GetAxis ("Mouse Y") * this.mouseYAxis;
    this.mouseScrollWheelDirection = Input.GetAxis ("Mouse ScrollWheel");
    this.buttonDownLeftStatus = Input.GetMouseButtonDown ((int)UMouseTypeEnum.LEFT);
    this.buttonLeftStatus = Input.GetMouseButton ((int)UMouseTypeEnum.LEFT);
    this.buttonRightStatus = Input.GetMouseButton ((int)UMouseTypeEnum.RIGHT);
    this.buttonUpLeftStatus = Input.GetMouseButtonUp ((int)UMouseTypeEnum.LEFT);
    if (!buttonLeftStatus && Input.GetKey (KeyCode.Q)) this.horizontalQEDirection = -1f;
    if (!buttonLeftStatus && Input.GetKey (KeyCode.E)) this.horizontalQEDirection = 1f;
    this.jumpStatus = Input.GetKey (KeyCode.Space);
    this.shiftLeftStatus = Input.GetKey (KeyCode.LeftShift);
    this.shiftRightStatus = Input.GetKey (KeyCode.RightShift);
}

void Update()
{
    if (this.cameraTransform == null) return;

    this.InitInputData ();

    // 获取地面状态
    bool groundStatus = this.IsGrounded ();

    if (groundStatus && this.jumpStatus && !this.isJumping) 
    {
        this.isJumping = true;
        this.verticalVelocity = this.jumpVelocity;
    }

    if (this.isJumping && this.verticalVelocity >= 0f) 
    {
        this.verticalVelocity = Mathf.SmoothDamp(this.verticalVelocity, -this.dropVelocity, ref this.currentJumpVelocity, 0.15f);
    }
    else
    {
        this.isJumping = false;
        this.verticalVelocity = -this.dropVelocity;
    }

    // 如果按住滚轮 
    if (this.mouseScrollWheelDirection != 0) 
    { 
        if (this.cameraDistance >= this.cameraZoomNear && this.cameraDistance <= this.cameraZoomFar) 
        { 
            this.cameraDistance -= this.mouseScrollWheelDirection * this.mouseWheelVelocity; 
        } 
        if (this.cameraDistance < this.cameraZoomNear) 
        { 
            this.cameraDistance = this.cameraZoomNear; 
        } 
        if (this.cameraDistance > this.cameraZoomFar) 
        { 
            this.cameraDistance = this.cameraZoomFar; 
        } 
        this.cameraDistance = Mathf.Max(0.01f, this.cameraDistance);
    }
    // 如果鼠标左键按下状态
    if (this.buttonDownLeftStatus) 
    {
        this.prevMouseX = mouseX;
        this.prevMouseY = mouseY;
        this.prevForward = this.cameraTransform.TransformDirection(Vector3.forward);
    }
    // 如果按下鼠标左键或者按下鼠标右键
    if (this.buttonLeftStatus || this.buttonRightStatus) 
    {
        this.mouseX += this.mouseXDirection;
        this.mouseY += this.mouseYDirection;
    } 
    else
    {
        this.mouseX += 0f;
        this.mouseY += 0f;
    }
    // 如果鼠标左键松开
    if (this.buttonUpLeftStatus) 
    {
        this.mouseX = this.prevMouseX;
        this.mouseY = this.prevMouseY;
    }
    // 如果按下了水平方向键,并且鼠标未按下,左右转换视角
    if (this.horizontalDirection != 0f && (!this.buttonLeftStatus && !this.buttonRightStatus)) 
    {
        if (this.horizontalDirection > 0) 
        {
            this.mouseX = Mathf.SmoothDamp (this.mouseX, this.mouseX + 90f, ref this.mouseXVelocity, 0.2f);
        } 
        else
        {
            this.mouseX = Mathf.SmoothDamp (this.mouseX, this.mouseX - 90f, ref this.mouseXVelocity, 0.2f);
        }
    } 
    // 如果按下了水平方向键,并且鼠标右键,左右移动
    else if(this.horizontalDirection != 0f && this.buttonRightStatus)
    {
        this.horizontalQEDirection = this.horizontalDirection;
    }

    this.mouseY = Mathf.Clamp (this.mouseY, this.cameraClampMin, this.cameraClampMax);

    Quaternion xQuaternion = Quaternion.AngleAxis (this.mouseX, Vector3.up);
    Quaternion yQuaternion = Quaternion.AngleAxis (this.mouseY, Vector3.left);
    // 当前旋转角度
    this.prevQuaternion = xQuaternion * yQuaternion;
    // 如果Q、E水平移动
    if (this.horizontalQEDirection != 0) 
    {
        if (this.verticalDirection != 0f)
        {
            // 如果水平轴大于零,比如按下了 D 键
            if(this.horizontalQEDirection > 0)
            {
                xQuaternion = Quaternion.AngleAxis(this.mouseX + this.offsetAngle * 0.5f, Vector3.up);
            }
            else // 如果水平轴小于零,比如按下了 A 键
            {
                xQuaternion = Quaternion.AngleAxis(this.mouseX - this.offsetAngle * 0.5f, Vector3.up);
            }
        }
        else
        {
            // 如果水平轴大于零,比如按下了 D 键
            if(this.horizontalQEDirection > 0)
            {
                xQuaternion = Quaternion.AngleAxis(this.mouseX + this.offsetAngle, Vector3.up);
            }
            else // 如果水平轴小于零,比如按下了 A 键
            {
                xQuaternion = Quaternion.AngleAxis(this.mouseX - this.offsetAngle, Vector3.up);
            }
        }
    }
    if (!this.buttonLeftStatus) 
    {
        this.transform.rotation = xQuaternion;
    }
    // 摄像机对象的偏离位置,相对于角色头部位置
    this.cameraTransform.localPosition = new Vector3 (0f, 0f, this.headTransform.transform.localPosition.z - this.cameraDistance);
    // 如果按住了 Shift 键
    if (this.shiftLeftStatus || this.shiftRightStatus) 
    {
        this.speed = this.walkSpeed;
        this.roleActionEnum = URoleActionEnum.WALK;
    } else {
        this.speed = this.runSpeed;
        this.roleActionEnum = URoleActionEnum.RUN;
    }
     
    if (verticalDirection < 0f) 
    {
        this.speed = this.retreatSpeed;
        this.roleActionEnum = URoleActionEnum.RETREAT;
    }
     
    this.horizontalValue = this.horizontalQEDirection * this.speed * Time.deltaTime;
    this.verticalValue = this.verticalDirection * this.speed * Time.deltaTime;
    // 如果在跳起状态
    if (this.isJumping) this.roleActionEnum = URoleActionEnum.JUMP;
     
    if (this.horizontalQEDirection == 0f && this.horizontalDirection == 0f && this.verticalValue == 0f && !this.isJumping) this.roleActionEnum = URoleActionEnum.IDLE;
     
    Vector3 forward = this.cameraTransform.TransformDirection (Vector3.forward);
    if (this.buttonLeftStatus) forward = this.prevForward;

    forward.y = 0;
    forward = forward.normalized;
     
    Vector3 right = new Vector3 (forward.z, 0, -forward.x);
    // 设置移动向量
    this.moveDirection = this.horizontalValue * right + this.verticalValue * forward + new Vector3 (0, this.verticalVelocity * Time.deltaTime, 0);
     
    // 设置对象状态动画
    this.ChangeAction (this.roleActionEnum);
     
    this.characterController.Move (this.moveDirection);
}

private void ChangeAction(string roleActionEnum)
{
    if(roleActionEnum == URoleActionEnum.IDLE)
    {
        this.animation.CrossFade(this.idleClip.name);
    }
    else if(roleActionEnum == URoleActionEnum.WALK)
    {
        this.animation.CrossFade(this.walkClip.name);
    }
    else if(roleActionEnum == URoleActionEnum.RUN)
    {
        this.animation.CrossFade(this.runClip.name);
    }
    else if(roleActionEnum == URoleActionEnum.JUMP)
    {
        this.animation.CrossFade(this.jumpClip.name);
    }
    else if(roleActionEnum == URoleActionEnum.RETREAT)
    {
        this.animation.CrossFade(this.retreatClip.name);
    }
}

void LateUpdate ()
{
    if (this.cameraTransform == null) return;

    // 设置头部旋转
    this.headTransform.rotation = this.prevQuaternion;
    // 下面代码保证视角内没有透视区域
    RaycastHit hitCamera = new RaycastHit ();
    RaycastHit[] hits = Physics.SphereCastAll (this.headTransform.position, 0.3f * 0.5f, -this.cameraTransform.forward, this.cameraDistance);
    hitCamera.distance = Mathf.Infinity;
    foreach (RaycastHit hit in hits) 
    {
        //判断是否是地形
        Terrain terrain = hit.transform.GetComponent<Terrain>();
        if (hit.distance < hitCamera.distance && hit.transform != this.transform.transform && terrain != null) 
        {
            bool found = false;
            if (this.transform.transform.childCount > 0) 
            {
                foreach (Transform childTransform in this.transform) 
                {
                    if (hit.transform == childTransform) 
                    {
                        found = true;
                        break;
                    }
                }
            }
            if (!found) hitCamera = hit;
        }
    }
    if (hitCamera.distance != Mathf.Infinity) 
    {
        this.cameraDistance -= this.cameraReviseDistance;
    }
}

protected virtual bool IsGrounded () 
{
    return (this.characterController.collisionFlags == CollisionFlags.CollidedBelow);
}

}

UMouseTypeEnum.cs

using UnityEngine;
using System.Collections;

public enum UMouseTypeEnum
{
LEFT = 0,
RIGHT = 1
}

URoleActionEnum.cs :

using UnityEngine;
using System.Collections;

public class URoleActionEnum
{
public const string IDLE = “idle”;

public const string WALK = "walk";

public const string RUN = "run";

public const string RETREAT = "retreat";

public const string JUMP = "jump";

public const string ATTACK = "attack";

public const string MAGIC = "magic";

public const string DIE = "die";

}