3D RPG Course | Core | Unity学习笔记(二)

(一)创建并编写第一个脚本-鼠标控制NavMesh目的地

        在资源管理其中创建脚本文件,作为一个MonoBehaviour子类,脚本可以挂载到一个空的游戏对象上。
        MouseManager.cs是一个用鼠标点击场景并移动的脚本,可通过构造鼠标点击事件实现。在脚本类中创建一个Event对象并在外面序列化,这样在unity的inspector中就可以看到event框,在其中添加一项角色的对象,在功能中存在NavMeshAgent的选项,说明只要把鼠标点击的位置信息传给NavMeshAgent.destination即可自动完成寻路。

        Event的使用需要先创建一个类

[Serializable]

public class StringEvent : UnityEvent <string> {}

        然后在脚本的类中添加上面的类即可使用,可通过XXX.Invoke(String)来调用Event。

       

        接下来实现判断鼠标所点击的位置。使用Camera.ScreenPointToRay来生成一条射线,使用Physics.RayCast来计算射线碰撞的数据。

        首先按帧检测射线并手机碰撞信息,然后判断鼠标是否点击、射线是否碰撞以及是否点击到了地面(使用tag判断),最后将点击到的位置信息(碰撞位置)发送到Event绑定的对象中(something?.xxx表示判断something是否为空,不为空则执行后面的方法)。最后将需要实时判断的函数都放入Update中。

        角色移动时的参数等可在角色对象的NavMesh Agent组件上调整。

(二)让游戏随时都能调用脚本

       希望不用把角色拖拽到Event列表中也能受控的话,可以将MouseManager写成单例模式。

单例模式是游戏脚本中唯一存在的,无论何时何地都可以通过XXX.Instance来访问调用的类写法,常用于需要在不同场景调用的功能,如菜单栏,音量控制等。简单的的写法为:

public class MouseManager : MonoBehaviour
{

    public static MouseManager Instance;
    void Awake()
     {
         if(Instance != null)
         {
             Destroy(Instance);
         }
         Instance = this;
     }


}

        之后需要创建一个新的脚本来调用单例。初始设置要在Awake函数中进行,以防止空引用等情况(Awake运行位置很靠前,几乎是游戏一开始)。在MouseManager.cs中修改Event写法,注意在点击地面导致Event调用Invoke启用后,所有订阅了这个Event的方法都会被执行,所有要让PlayerController.cs中的移动方法使用“+=”来订阅这个单例中的事件(注意参数一致)。实现方法完成后将控制脚本添加到角色对象上。

(三)更换鼠标指针

        指针所用的图像应为png格式图片,将TextureType设为Cursor可使背景变为透明,图片设置可更改(如大小尺寸)。

        在脚本中创建Texture2D变量,并在并在unity中的Mouse Manager对象中设置变量的值为所需要的指针图标。然后在SetCursorTexture方法中实现分情况的鼠标图标切换。CursorMode参数控制光标渲染方式,Auto为在支持的平台使用硬件光标,ForceSoftware则强制使用软件光标,当修改图片尺寸无法改变光标大小时,可以改为CursorMode.ForceSoftware。

MouseManager.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEditor.PackageManager;
using UnityEngine;
//using UnityEngine.Events;//引用Events命名空间来构造事件。
using System;



/// <summary>
/// [System.Serializable]//序列化,EventVector3才能在unity编辑界面被显示出来
///public class EventVector3 : UnityEvent<Vector3>{}//引用UnityEngine.Events中的UnityEvent<>来构造事件类
/// </summary>//由于改用单例模式来进行事件控制,此部分不再生效
public class MouseManager : MonoBehaviour
{

    public static MouseManager Instance;//单例模式化

    public Texture2D point, doorway, attack, target, arrow;//鼠标指针图标
    RaycastHit hitInfo;//储存摄像头发出射线所碰撞的具体信息
    //public EventVector3 OnMouseClicked;
    public event Action<Vector3> OnMouseClicked;

   void Awake()
    {
        if(Instance != null)//单例模式化
        {
            Destroy(Instance);
        }
        Instance = this;
    }

    void Update()//按帧运行
    {
        SetCursorTexture();
        MouseControl();
    }

    void SetCursorTexture()//设置指针贴图
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//以主摄像头创建射线,ScreenPointToRay方法在创建
                                                      //射线时需要一个vector参数,以鼠标输入为参数
        if(Physics.Raycast(ray,out hitInfo))
        {
            //切换鼠标贴图
            switch (hitInfo.collider.gameObject.tag)
            {
                case "Ground":
                    //CursorMode.ForceSoftware是强制使用软件光标
                    Cursor.SetCursor(target,new Vector2(16,16),CursorMode.ForceSoftware);//设置指针参数,第二个变量为指针有效点相对于左上角的偏移
                    break;
            }
        }
    }

    void MouseControl()
    {
        if(Input.GetMouseButtonDown(0) && hitInfo.collider != null)//鼠标左键按下且射线碰撞不为空
        {
            if(hitInfo.collider.gameObject.CompareTag("Ground"))//利用Tag判断是否点击到了地面
            {
                OnMouseClicked?.Invoke(hitInfo.point);//将坐标传给事件
            }
        }
    }


}

PlayerController.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;//用于调用NavMeshAgent

public class PlayerController : MonoBehaviour
{
    private NavMeshAgent agent;

    private void Awake()
    {
        agent = GetComponent<NavMeshAgent>();//获得NavMeshAgent方法
    }

    private void Start()
    {
        MouseManager.Instance.OnMouseClicked+=MoveToTarget;//将方法注册到事件中,每当事件启用就会执行该方法

    }

    public void MoveToTarget(Vector3 target)//参数要与注册事件的参数一致
    {
        agent.destination = target;
    }

}

(四)相机跟踪Cinemachine

        相机跟踪使用Cinemachine包实现。先使用Cinemachine创建一个虚拟摄像机,在其VirtualCamera组件中Body控制如何移动,aim控制如何旋转,follow设定要跟随的对象。

        

Body属性提供了下列算法来移动虚拟相机:

  • Do Nothing:不移动虚拟相机
  • Framing Transposer:在屏幕空间,保持相机和跟随目标的相对位置,可以设置缓动。
  • Hard Lock to Target:虚拟相机和跟随目标使用相同位置。
  • Orbital Transposer:相机和跟随目标的相对位置是可变的,还能接收用户的输入。常见于玩家控制的相机。
  • Tracked Dolly:相机沿着预先设置的轨道移动。
  • Transposer:相机和跟随目标的相对位置固定,可以设置缓动。

Aim属性提供了下列算法来旋转相机对准Look At的目标:

  • Composer:将目标保持在相机镜头内,可以设置多种约束
  • Group Composer:将多个目标保持在相机镜头内
  • Do Nothing:不旋转相机
  • POV:根据用户的输入旋转相机
  • Same As Follow Target:将相机的旋转和跟随目标的旋转同步
  • Hard Look At:将Look At目标固定在镜头中心的位置。

        如果向让摄像机跟随物体中心点以外的位置,可以在物体上创建一个子对象,让摄像机跟随这个子对象的中心。

(五)添加迷雾效果和后处理

        迷雾效果在window-rendering-lighting-environment中启用,可以设置颜色,可见度等参数。

        安装URP后系统就自带了后处理功能,在Hierarchy中右键的Volume中选择全局或部分区域的后处理。在创建的Volume对象中设置效果,并在mainCinema中启用postProcessing即可。

        具体如何添加后处理可参照官方文档,全部效果包括:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值