Unity一个脚本里写2个类遇到的问题

本文探讨了在Unity引擎中使用C#编程时,不同类继承MonoBehaviour的情况下this关键字及transform属性的使用限制。实验证明,只有与脚本名称相同的类才能正常使用this指代自身。

最近遇到的问题,记录一下:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

上面是代码和运行结果,Debug.Log("t2: " + transform.position.x); 这一句会报错
调试显示this 是null

我的结论是因为test1和脚本名一致,又继承了MonoBehaviour,所以可以使用this指代自己
test2就不行了


上面是实验,我实际是在MonoBehaviour插件里写脚本时遇到的,脚本名A,一个类A继承了Action,另一个类B里就不能用this,直接用tranform也不行。我估计一个脚本里只有一个类里能用this,就是那个和脚本名同名的类


补充一下:一个脚本里2个类继承MonoBehaviour,与脚本名不同的那个,start方法不会自动执行,估计update等方法也是。这个可能就被系统认为是个普通类了吧
但继承了MonoBehaviour之后,可以用一些方法,如果不继承,还不能使用。

如果有大佬看到,发现这是错的,还望留言指正。

<think>我们正在为Unity游戏开发编一个鼠标移动控制脚本。用户希望在Visual Studio2019中实现。主要目标:通过鼠标移动来控制游戏物体的旋转(通常是摄像机或角色),实现第一人称或第三人称的视角控制。步骤:1.在Unity中创建一个C#脚本2.在VisualStudio2019中打开并编辑该脚本。3.编代码,使用Input.GetAxis("MouseX")和Input.GetAxis("MouseY")来获取鼠标移动。4.根据鼠标移动旋转物体(注意:通常水平移动(MouseX)控制绕Y轴的旋转,垂直移动(MouseY)控制绕X轴的旋转)。5.注意处理垂直旋转时的限制(避免翻转过度)。6.将脚本挂载到游戏物体(如主摄像机或玩家物体)上。注意:在Unity中,旋转通常使用欧拉角(EulerAngles)或四元数(Quaternion)来实现。这我们使用欧拉角,因为它更直观。我们将编一个简单的脚本,实现用鼠标控制物体旋转(似第一人称视角控制)。代码结构:-定义两个公共变量:鼠标灵敏度(mouseSensitivity)和垂直旋转角度限制(上下最大角度)。-在Update函数中获取鼠标输入。-计算水平旋转(影响物体的Y轴旋转)和垂直旋转(影响物体局部X轴的旋转)。-注意:垂直旋转通常需要累计并限制在一定范围内,避免过度翻转。另外,注意Unity的坐标系:Y轴向上,X轴向右,Z轴向前。旋转时,绕Y轴旋转是水平旋转,绕X轴旋转是垂直旋转。但是,注意:当我们旋转物体时,垂直旋转(MouseY)应该影响物体绕其局部X轴的旋转(抬头低头),而水平旋转(Mouse X)影响绕世界Y轴(或物体局部Y轴)的旋转(左右转)。然而,为了不产生万向节死锁,我们通常将水平旋转应用于父物体(如一个空物体作为玩家),垂直旋转应用于子物体(如摄像机)。但这我们简化处理,假设只有一个物体(比如摄像机)同时处理水平和垂直旋转。但是,同时在一个物体上旋转水平和垂直会导致万向节死锁?实际上,对于简单的第一人称视角,我们通常分开处理:水平旋转用物体的Y轴,垂直旋转用物体的X轴(并且限制角度)。这样虽然可能在某些角度有死锁,但通常在小角度旋转时没有问题。另一种常见做法:将水平旋转应用于玩家物体(父物体),垂直旋转应用于摄像机(子物体)。这样垂直旋转只影响摄像机,水平旋转影响整个玩家(包括摄像机)。这样避免了万向节死锁,并且更符合实际(玩家身体左右转,同时抬头低头)。因此,我们假设用户需要控制一个物体(比如玩家)的水平旋转和其上的摄像机(子物体)的垂直旋转。但用户问题中只提到一个脚本,所以我们可以有两种方式:-方式1:一个脚本同时控制两个物体(如果有父子关系,则分别旋转父物体和子物体)。-方式2:只控制一个物体(比如摄像机),同时旋转水平和垂直(但可能不自然,因为垂直旋转会影响水平轴)。这我们采用更常见的分离方式:脚本挂载在玩家物体(父物体)上,然后控制玩家物体的水平旋转,同时控制其子物体(摄像机)的垂直旋转。但如果用户没有父子物体,我们可以先建议用户创建这样的结构。因此,脚本设计如下:假设场景中有一个玩家物体(Player),它有一个子物体MainCamera(摄像机)。脚本挂载在Player上。步骤:1.获取鼠标输入。2.水平旋转:玩家物体绕Y轴旋转(MouseX)。3.垂直旋转:摄像机绕X轴旋转(Mouse Y),并且累计垂直旋转角度,限制在[-80,80]度之间。代码实现:注意:在Unity中,旋转使用Transform组件的Rotate方法,或者直接设置localEulerAngles。这我们使用欧拉角,并直接设置旋转。但是,直接设置欧拉角可能会遇到0-360跳变问题,所以我们使用一个变量来累计垂直旋转角度,然后限制在最小和最大角度之间。具体代码:在Player物体上挂载脚本,然后需要指定一个摄像机的Transform(可以public拖拽,或者自动查找子物体中的摄像机)。我们将在脚本中:-定义一个Transform变量camTransform,用于指向子物体摄像机。-在Start函数中,如果没有指定,则尝试获取子物体的摄像机。另外,注意:鼠标移动的方向与旋转方向的关系。通常,鼠标向上移动(MouseY为正)时,我们想要向下看(即摄像机绕X轴负方向旋转),反之亦然。所以垂直旋转时,我们用负的Mouse Y。代码示例:</think>### 在 Unity 中使用 C# 编鼠标移动控制脚本(Visual Studio 2019 实现) 以下是实现鼠标控制游戏对象旋转的完整步骤和代码: #### 1. 创建 C# 脚本 1. 在 Unity 的 Project 窗口右键 → Create → C# Script 2. 命名为 `MouseLookController` 3. 双击脚本在 Visual Studio 2019 中打开 #### 2. 编鼠标控制代码 ```csharp using UnityEngine; public class MouseLookController : MonoBehaviour { [Header("旋转设置")] public float mouseSensitivity = 100f; // 鼠标灵敏度 public Transform playerBody; // 玩家身体(水平旋转对象) public Transform cameraPivot; // 摄像机支点(垂直旋转对象) [Header("视角限制")] public float minVerticalAngle = -80f; // 垂直最小角度 public float maxVerticalAngle = 80f; // 垂直最大角度 private float xRotation = 0f; // 垂直旋转累计值 void Start() { Cursor.lockState = CursorLockMode.Locked; // 锁定鼠标到屏幕中心 } void Update() { // 获取鼠标输入(使用平滑处理的原始输入) float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime; float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime; // 垂直旋转计算(反向且带角度限制) xRotation -= mouseY; xRotation = Mathf.Clamp(xRotation, minVerticalAngle, maxVerticalAngle); // 应用垂直旋转(仅影响摄像机支点) cameraPivot.localRotation = Quaternion.Euler(xRotation, 0f, 0f); // 应用水平旋转(影响整个玩家身体) playerBody.Rotate(Vector3.up * mouseX); } } ``` #### 3. 场景设置步骤 1. **创建玩家层级结构**: ```plaintext Player (空对象,挂载脚本) ├── Body (玩家模型) └── CameraPivot (空对象) └── Main Camera (摄像机) ``` 2. **脚本挂载**: - 将 `MouseLookController` 挂载到 Player 对象 - 在 Inspector 中关联: - `Player Body` → Body 对象 - `Camera Pivot` → CameraPivot 对象 #### 4. 关键功能说明 1. **双旋转系统**: - 水平旋转(`Mouse X`)作用于玩家身体 - 垂直旋转(`Mouse Y`)作用于摄像机支点 - 避免万向节死锁问题[^1] 2. **物理正确性**: - 使用 `Time.deltaTime` 确保帧率无关的平滑旋转 - 旋转计算:$\Delta\theta = \Delta mouse \times sensitivity \times \Delta t$ 3. **视角限制**: - 垂直旋转角度限制在 $[\theta_{min}, \theta_{max}]$ 区间 - 使用 `Mathf.Clamp()` 实现:$xRotation = \max(\min(xRotation, \theta_{max}), \theta_{min})$ #### 5. 常见问题解决 1. **脚本编译错误**: - 确保 Visual Studio 安装了 Unity 开发组件[^2] - 检查 Unity → Preferences → External Tools 中的 VS 路径配置 2. **鼠标不锁定**: - 在 `Start()` 中确认执行了 `Cursor.lockState = CursorLockMode.Locked` - 按 Esc 键可解除锁定 3. **旋转方向相反**: - 调整 `mouseY` 计算符号:`xRotation += mouseY` 或 `xRotation -= mouseY` - 修改 `mouseSensitivity` 的符号值 #### 6. 优化建议 ```csharp // 在中添加可选的平滑滤波 [Header("高级设置")] public bool useSmoothing = true; public float smoothingFactor = 10f; private float currentHorizontal; private float currentVertical; void Update() { float targetHorizontal = currentHorizontal + Input.GetAxis("Mouse X") * mouseSensitivity; float targetVertical = xRotation - Input.GetAxis("Mouse Y") * mouseSensitivity; if(useSmoothing) { currentHorizontal = Mathf.Lerp(currentHorizontal, targetHorizontal, smoothingFactor * Time.deltaTime); currentVertical = Mathf.Lerp(currentVertical, targetVertical, smoothingFactor * Time.deltaTime); } else { currentHorizontal = targetHorizontal; currentVertical = targetVertical; } xRotation = Mathf.Clamp(currentVertical, minVerticalAngle, maxVerticalAngle); playerBody.rotation = Quaternion.Euler(0, currentHorizontal, 0); cameraPivot.localRotation = Quaternion.Euler(xRotation, 0, 0); } ``` #### 7. 平台适配 - **PC 端**:直接使用上述脚本 - **移动端**:需替换鼠标输入为触摸输入 ```csharp // 在移动设备上使用触摸输入 if (Application.isMobilePlatform) { if (Input.touchCount > 0) { Touch touch = Input.GetTouch(0); mouseX = touch.deltaPosition.x * mobileSensitivity; mouseY = touch.deltaPosition.y * mobileSensitivity; } } ``` [^1]: 分离水平和垂直旋转轴可避免万向节死锁问题,这是3D旋转中的常见约束。 [^2]: 需安装 "使用 Unity 的游戏开发" 工作负载,可通过 Visual Studio Installer 添加。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值