Unity例子——第一人称视角的角色控制器

简介: Unity例子——第一人称视角的角色控制器

本文是为了前文Unity四元组的举例示范,为了让读者更好地理解。


效果是实现一个可以由鼠标进行方向操作,键盘进行移动操作的任务。

此为效果视频:

1687597097844


下面进行教学:

一、搭建简单场景

  1. 新建一个场景,放置一个plane作为地板,尺寸自定
  2. 创建一个新的material挂在plane上
  3. 再地板上放置一些cube,主要是为了在测试时作为参照物

二、创建主角物体

  1. 创建一个capsule,代表一个角色
  2. 创建一个cube作为capsule的子物体,将立方体放在capsule的“脸”部。挂上材质
  3. 拖曳场景列表中的著摄像机,让著摄像机变成capsule的子物体
  4. 将著摄像机的位置归0,然后微调著摄像机的位置到角色的脸部

三、编写控制脚本——移动部分

  1. 创建脚本FPSCharacter,将其挂载于capsule上
  2. 编写脚本内容。脚本内容是重点,下面分步介绍

角色的控制分为两大块:角色移动和摄像机旋转

角色移动方面,玩家可以按方向键进行前后左右平移。问题是;玩家按上方向键时,对应哪个方向;玩家按右方向键时,又对应哪个方向。

一般玩家本身具有前方向量transform.forward和右方向量transform.right。右方向量与右方向的移动直接对应;前方向量比较麻烦,因为存在抬头,低头的情况。如果玩家在抬头看天时直接向前方走,就会得到向天上飞的结果。

解决方案是得到前方向量后,略加修改,去除前方向量的y轴分量,这样就让前方向量保持水平了。整段代码在文章末尾,计算移动的部分代码如下

 void Move()
    {
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");
        Vector3 fwd = transform.forward;
        Vector3 f = new Vector3(fwd.x, 0, fwd.z).normalized;
        Vector3 r = transform.right;
        Vector3 move = f * z + r * x;
        transform.position += move * speed * Time.deltaTime;
    }

四、编写控制脚本——旋转部分

接下来是旋转镜头部分。由于著摄像机已经挂在角色身上,因此直接旋转角色,镜头就会跟着旋转。其旋转的关键代码如下

 void MouseLook()
    {
        float mx = Input.GetAxis("Mouse X");
        float my = -Input.GetAxis("Mouse Y");
        Quaternion qx = Quaternion.Euler(0, mx, 0);
        Quaternion qy = Quaternion.Euler(my, 0, 0);
        transform.rotation = qx * transform.rotation;
        transform.rotation = transform.rotation*qy;
    }

鼠标移动旋转物体的思路并不简单,但是巧妙利用四元数之后,代码出乎意料的简短。首先,“Mouse X”和“Mouse Y”是两个特殊的输入轴,分别对应的是鼠标的横向移动和纵向移动(不是鼠标位置,而是鼠标位置的变化量)

鼠标横向移动对应的是镜头水平旋转,即沿y轴旋转;鼠标纵向移动对应的是镜头俯仰旋转。因此可以将鼠标的横向、纵向移动当作欧拉角,并转化成四元数,这样就得到了两个”小旋转“,分别叫做qx和qy。

之后只要用四元数乘法将小旋转应用于角色当前朝向,问题就解决了。难点在于,镜头水品那个旋转实际上是沿世界坐标系的y轴旋转,而镜头俯仰旋转则是围绕局部坐标系的x轴旋转。

最后,因为人们在低头、抬头动作时,不能超过90°看到自己的后面,所以要对俯仰角度作出限制,因此需要在MouseLook()函数尾部补上以下一段逻辑。

 float angle = transform.eulerAngles.x;
        if (angle > 180) { angle -= 360; }
        if (angle <- 180) { angle+= 360; }
        if(angle>80)
        {
            Debug.Log("A" + transform.eulerAngles.x);
            transform.eulerAngles = new Vector3(80, transform.eulerAngles.y, 0);
        }
        if (angle <-80)
        {
            Debug.Log("A" + transform.eulerAngles.x);
            transform.eulerAngles = new Vector3(-80, transform.eulerAngles.y, 0);
        }

五、隐藏并锁定鼠标指针

测试时,会发现鼠标指针会影响游戏体验,如果单击到Game窗口之外的区域,Game窗口就会失去焦点。解决方法是隐藏鼠标指针,并把鼠标指针锁定到屏幕中央,代码如下

void Start()
    {
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;
    }

Unity编译器中,只需要按下Esc键就会显示出鼠标指针了,而在实际游戏开发者能够,别忘了在合适的时机将鼠标指针崇信县属出来,并取消锁定。如原神中就是摁Alt键取消锁定的。

六、完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FPSCharachter : MonoBehaviour
{
    public float speed = 5f;
    void Start()
    {
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.Locked;
    }
    void Update()
    {
        Move();
        MouseLook();
    }
   void Move()
    {
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");
        Vector3 fwd = transform.forward;
        Vector3 f = new Vector3(fwd.x, 0, fwd.z).normalized;
        Vector3 r = transform.right;
        Vector3 move = f * z + r * x;
        transform.position += move * speed * Time.deltaTime;
    }
    void MouseLook()
    {
        float mx = Input.GetAxis("Mouse X");
        float my = -Input.GetAxis("Mouse Y");
        Quaternion qx = Quaternion.Euler(0, mx, 0);
        Quaternion qy = Quaternion.Euler(my, 0, 0);
        transform.rotation = qx * transform.rotation;
        transform.rotation = transform.rotation * qy;
        float angle = transform.eulerAngles.x;
        if (angle > 180) { angle -= 360; }
        if (angle <- 180) { angle+= 360; }
        if(angle>80)
        {
            Debug.Log("A" + transform.eulerAngles.x);
            transform.eulerAngles = new Vector3(80, transform.eulerAngles.y, 0);
        }
        if (angle <-80)
        {
            Debug.Log("A" + transform.eulerAngles.x);
            transform.eulerAngles = new Vector3(-80, transform.eulerAngles.y, 0);
        }
    }
}


相关文章
|
9天前
|
图形学
unity Camera第一人称移动
第一人称视角移动模拟通过检测用户键盘和鼠标输入,实现场景中的位置移动和视角旋转。位置移动基于W、A、S、D键控制相机前后左右移动,视角旋转通过鼠标控制上下左右观察,避免翻转并限制旋转角度。代码使用Unity的Input类和Transform方法实现这些功能,确保流畅的第一人称体验。
|
6月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
331 6
|
6月前
|
图形学 机器学习/深度学习 人工智能
颠覆传统游戏开发,解锁未来娱乐新纪元:深度解析如何运用Unity引擎结合机器学习技术,打造具备自我进化能力的智能游戏角色,彻底改变你的游戏体验——从基础设置到高级应用全面指南
【8月更文挑战第31天】本文探讨了如何在Unity中利用机器学习增强游戏智能。作为领先的游戏开发引擎,Unity通过ML-Agents Toolkit等工具支持AI代理的强化学习训练,使游戏角色能自主学习完成任务。文章提供了一个迷宫游戏示例及其C#脚本,展示了环境观察、动作响应及奖励机制的设计,并介绍了如何设置训练流程。此外,还提到了Unity与其他机器学习框架(如TensorFlow和PyTorch)的集成,以实现更复杂的游戏玩法。通过这些技术,游戏的智能化程度得以显著提升,为玩家带来更丰富的体验。
100 1
|
5月前
|
vr&ar 图形学 API
Unity与VR控制器交互全解:从基础配置到力反馈应用,多角度提升虚拟现实游戏的真实感与沉浸体验大揭秘
【8月更文挑战第31天】虚拟现实(VR)技术迅猛发展,Unity作为主流游戏开发引擎,支持多种VR硬件并提供丰富的API,尤其在VR控制器交互设计上具备高度灵活性。本文详细介绍了如何在Unity中配置VR支持、设置控制器、实现按钮交互及力反馈,结合碰撞检测和物理引擎提升真实感,助力开发者创造沉浸式体验。
272 0
|
5月前
|
图形学 开发者
透视与正交之外的奇妙视界:深入解析Unity游戏开发中的相机与视角控制艺术,探索打造沉浸式玩家体验的奥秘与技巧
【8月更文挑战第31天】在Unity中,相机不仅是玩家观察游戏世界的窗口,更是塑造氛围和引导注意力的关键工具。通过灵活运用相机系统,开发者能大幅提升游戏的艺术表现力和沉浸感。本文将探讨如何实现多种相机控制,包括第三人称跟随和第一人称视角,并提供实用代码示例。
246 0
|
6月前
|
开发者 图形学 C#
深度解密:Unity游戏开发中的动画艺术——Mecanim状态机如何让游戏角色栩栩如生:从基础设置到高级状态切换的全面指南,助你打造流畅自然的游戏动画体验
【8月更文挑战第31天】Unity动画系统是游戏开发的关键部分,尤其适用于复杂角色动画。本文通过具体案例讲解Mecanim动画状态机的使用方法及原理。我们创建一个游戏角色并设计行走、奔跑和攻击动画,详细介绍动画状态机设置及脚本控制。首先导入动画资源并添加Animator组件,然后创建Animator Controller并设置状态间的转换条件。通过编写C#脚本(如PlayerMovement)控制动画状态切换,实现基于玩家输入的动画过渡。此方法不仅适用于游戏角色,还可用于任何需动态动画响应的对象,增强游戏的真实感与互动性。
168 0
|
8月前
|
图形学
【推荐100个unity插件之9】分享几个完全免费的2D角色动画生成器(推荐收藏)
【推荐100个unity插件之9】分享几个完全免费的2D角色动画生成器(推荐收藏)
424 0
|
8月前
|
图形学
【unity小技巧】unity最完美的CharacterController 3d角色控制器,实现移动、跳跃、下蹲、奔跑、上下坡、物理碰撞效果,复制粘贴即用
【unity小技巧】unity最完美的CharacterController 3d角色控制器,实现移动、跳跃、下蹲、奔跑、上下坡、物理碰撞效果,复制粘贴即用
964 0
|
8月前
|
图形学
【用unity实现100个游戏之18】从零开始制作一个类CSGO/CS2、CF第一人称FPS射击游戏——基础篇3(附项目源码)
【用unity实现100个游戏之18】从零开始制作一个类CSGO/CS2、CF第一人称FPS射击游戏——基础篇3(附项目源码)
114 0
|
8月前
|
图形学
【用unity实现100个游戏之18】从零开始制作一个类CSGO/CS2、CF第一人称FPS射击游戏——基础篇2(附项目源码)
【用unity实现100个游戏之18】从零开始制作一个类CSGO/CS2、CF第一人称FPS射击游戏——基础篇2(附项目源码)
140 0