Unity 网络游戏黑暗之光笔记

第三章 创建游戏运行场景及角色控制

1. 创建场景导入资源等

2. 标签管理

  • 使用标签来进行判定,使用const减少代码的出错率
	//地面标签
	public const string ground = "Ground";//const 标明这个是一个共有的不可变的变量
	//玩家标签
    public const string player = "Player";

3. 鼠标控制人物移动

鼠标点击地面特效,在角色上挂载脚本脚本

Unity 游戏黑暗之光笔记第三章 创建游戏运行场景及角色控制_unity

   public GameObject effect_click_prefab;   
    void Update()
    {
        //检测鼠标的按下
        //将鼠标的坐标转换为射线该
        //射线与地面发生碰撞返回发生碰撞的点,然后让角色转向该点,开始移动。当移动到一定范围时停止移动。
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
            //保存碰撞信息
            RaycastHit hitInfo;
            bool isCollider = Physics.Raycast(ray, out hitInfo);
            if(isCollider&& hitInfo.collider.tag   ==Tags.ground)
            {
                //实例化点击的效果
                showClickEffect(hitInfo.point);
            }
        }
        void showClickEffect(Vector3 hitPoint)
        {
            hitPoint = new Vector3(hitPoint.x, hitPoint.y+0.1f,hitPoint.z);
            GameObject.Instantiate(effect_click_prefab, hitPoint, Quaternion.identity);
        }
    }
  • 控制主角的朝向(鼠标点击地面的时候转向)

增加两个对象

private Vector3 targetPosition = Vector3.zero;
private bool isMoving = false;//表示鼠标是否按下

在update方法的 if(isCollider&& hitInfo.collider.tag ==Tags.ground)中增加

 isMoving = true;
 LookAtTarget(hitInfo.point);

在update方法中增加两个判定语句

if (Input.GetMouseButtonUp(0))
        {
            isMoving = false;
        }
if (isMoving)
        {
            //得到要移动的目标位置
            //让主角朝向目标位置
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;
            bool isCollider = Physics.Raycast(ray, out hitInfo);
            if (isCollider && hitInfo.collider.tag == Tags.ground)
            {
                LookAtTarget(hitInfo.point);
            }
        }

增加一个lookat方法

void LookAtTarget(Vector3 hitPoint)
    {
        targetPosition = hitPoint;
        targetPosition = new Vector3(targetPosition.x, transform.position.y, targetPosition.z);
        this.transform.LookAt(targetPosition);
    }
  • 控制主角的移动,添PlayerMove脚本挂载到角色上

默认值是当前位置不会在游戏一开始时就运行在PlayDir脚本Start函数中添加
targetPosition = transform.position;

public float speed = 4;  
private PlayerDir dir;
private CharacterController controller;
void Start()
    {
        dir = this.GetComponent<PlayerDir>();
        controller = this.GetComponent<CharacterController>();
    }
void Update()
    {
        float distance = Vector3.Distance(dir.targetPosition, transform.position);
        if (distance > 0.3f)
        {
            isMoving = true;
            //state = PlayerState.Moving;
            controller.SimpleMove(transform.forward * speed);
        }
    }

添加人物动画

Unity 游戏黑暗之光笔记第三章 创建游戏运行场景及角色控制_unity_02

控制人物动画播放的脚本

using UnityEngine;
using System.Collections;
public class PlayerAnimation : MonoBehaviour
{
    private PlayerMove move;
    void Start()
    {
        move = this.GetComponent<PlayerMove>();
    }
    void LateUpdate()
    {
        if (move.state == PlayerState.Moving)
        {
            PlayAnim("Run");
        }
        else if (move.state == PlayerState.Idle)
        {
            PlayAnim("Idle");
        }
    }
    void PlayAnim(string animName)
    {
        GetComponent<Animation>().CrossFade(animName);
    }
}

注意在void PlayAnim方法中教程中使用的旧版的代码,新版的代码为

GetComponent<Animation>().CrossFade(animName);
  • 完善的PlayerDir代码
public class PlayerDir : MonoBehaviour
{

    public GameObject effect_click_prefab;
    public Vector3 targetPosition = Vector3.zero;
    private PlayerMove playerMove;
    private bool isMoving = false;//表示鼠标是否按下

    private void Start()
    {
        //默认值是当前位置不会在游戏一开始时就运行
        targetPosition = transform.position;
        playerMove = this.GetComponent<PlayerMove>();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;
            bool isCollider = Physics.Raycast(ray, out hitInfo);
            if (isCollider && hitInfo.collider.tag == Tags.ground)
            {
                isMoving = true;
                ShowClickEffect(hitInfo.point);
                LookAtTarget(hitInfo.point);
            }
        }

        if (Input.GetMouseButtonUp(0))
        {
            isMoving = false;
        }

        if (isMoving)
        { 
            //得到要移动的目标位置
            //让主角朝向目标位置
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;
            bool isCollider = Physics.Raycast(ray, out hitInfo);
            if (isCollider && hitInfo.collider.tag == Tags.ground)
            {
                LookAtTarget(hitInfo.point);
            }
        }
        else {
            if (playerMove.isMoving)
            {
                LookAtTarget(targetPosition);
            }
        }
    }
    //实例化出来点击的效果
    void ShowClickEffect(Vector3 hitPoint)
    {
        hitPoint = new Vector3(hitPoint.x, hitPoint.y + 0.1f, hitPoint.z);
        GameObject.Instantiate(effect_click_prefab, hitPoint, Quaternion.identity);
    }
    //让主角朝向目标位置
    void LookAtTarget(Vector3 hitPoint)
    {
        targetPosition = hitPoint;
        targetPosition = new Vector3(targetPosition.x, transform.position.y, targetPosition.z);
        this.transform.LookAt(targetPosition);
    }
}

4. 控制相机跟随主角的移动

  • 在主摄像机挂在FollowCamera脚本
private Transform player;
    private Vector3 offsetPosition;//位置偏移
    void Start()
    {
        player = GameObject.FindGameObjectWithTag(Tags.player).transform;
        //使相机永远朝向主角
        transform.LookAt(player.position);
        offsetPosition = transform.position - player.position;
    }
    void Update()
    {
        transform.position = offsetPosition + player.position;
    }
  • 使用鼠标滑动控制相机视野的拉近和拉远

定义一个 public float scrollSpeed = 10;
在上面的Update方法中增加 ScrollView();方法

void ScrollView()
    {
        //print(Input.GetAxis("Mouse ScrollWheel"));//向后 返回负值 (拉近视野) 向前滑动 返回正值(拉远视野)
        distance = offsetPosition.magnitude;
        //获取鼠标中键的值
        distance += Input.GetAxis("Mouse ScrollWheel") *- scrollSpeed;
        distance = Mathf.Clamp(distance, 2, 18);
        offsetPosition = offsetPosition.normalized * distance;
    }

注意要在distance += Input.GetAxis("Mouse ScrollWheel") *- scrollSpeed;中的
- scrollSpeed负号,才是与实际效果一致

  • 相机距离的限制
  distance = Mathf.Clamp(distance, 2, 18);
  • 相机的旋转
void RotateView()
    {
        //Input.GetAxis("Mouse X");//得到鼠标在水平方向的滑动
        //Input.GetAxis("Mouse Y");//得到鼠标在垂直方向的滑动
        if (Input.GetMouseButtonDown(1))
        {
            isRotating = true;
        }
        if (Input.GetMouseButtonUp(1))
        {
            isRotating = false;
        }

        if (isRotating)
        {
            transform.RotateAround(player.position, player.up, rotateSpeed * Input.GetAxis("Mouse X"));

            Vector3 originalPos = transform.position;
            Quaternion originalRotation = transform.rotation;

            transform.RotateAround(player.position, transform.right, -rotateSpeed * Input.GetAxis("Mouse Y"));//影响的属性有两个 一个是position 一个是rotation
            float x = transform.eulerAngles.x;
            if (x < 10 || x > 80)
            {//当超出范围之后,我们将属性归位原来的,就是让旋转无效 
                transform.position = originalPos;
                transform.rotation = originalRotation;
            }

        }

        offsetPosition = transform.position - player.position;
    }

注意方向函数的符号,还有update方法中调用的顺序

限定旋转的方向
 float x = transform.eulerAngles.x;
 if (x < 10 || x > 80)
            {//当超出范围之后,我们将属性归位原来的,就是让旋转无效 
                transform.position = originalPos;
                transform.rotation = originalRotation;
            }

5. 增加角色状态信息

给角色添加playerstatus脚本

    public int grade = 1;
    public int hp = 100;
    public int mp = 100;
    public int coin = 200;//金币数量
    public int attack = 20;
    public int attack_plus = 0;
    public int def = 20;
    public int def_plus = 0;
    public int speed = 20;
    public int speed_plus = 0;
    public int point_remain = 0;//剩余的点数