Unity基础:C#脚本的创建与挂载——让你的游戏物体活起来

Unity基础:C#脚本的创建与挂载------让你的游戏物体活起来

大家好,欢迎回到Unity教程系列。前面十五篇文章中,我们一直在学习场景搭建、组件操作、编辑器使用------这些都是"静态"的内容。从今天开始,我们要让游戏真正"动起来"了。而让游戏动起来的关键,就是编写C#脚本。

脚本是游戏逻辑的载体。角色的移动、敌人的AI、UI的交互、音效的播放------游戏中的一切动态行为,都来源于脚本。对于很多新手来说,第一次写脚本可能会感到紧张------别担心,这篇文章我会从最基础的操作开始,手把手带你进入Unity脚本编程的世界。

一、脚本在Unity中的角色

1.1 脚本是什么

💡 在Unity中,脚本(Script)是一种特殊的Component。当你创建一个C#脚本并将其挂载到GameObject上时,这个脚本就成为该GameObject的一个组件,拥有该组件的所有特性------可以在Inspector中查看、可以启用/禁用、可以通过GetComponent获取。

理解"脚本就是组件"这个观念非常重要。它意味着:

  • 脚本继承了MonoBehaviour(而MonoBehaviour继承了Component)
  • 脚本像其他组件一样,有生命周期(创建、启用、更新、禁用、销毁)
  • 脚本可以通过GetComponent被其他组件访问

1.2 脚本与GameObject的关系

每个挂载了脚本的GameObject都是该脚本的一个实例。如果你将同一个脚本挂载到10个不同的GameObject上,运行时会创建10个脚本实例,每个实例有自己独立的变量值。

复制代码
Player对象 ──── PlayerController脚本实例(moveSpeed=5)
Enemy_A对象 ── EnemyController脚本实例(moveSpeed=3)
Enemy_B对象 ── EnemyController脚本实例(moveSpeed=4)

二、创建脚本

2.1 在Unity中创建C#脚本

创建脚本有多种方式:

方式一:Project窗口右键

① 在Project窗口中进入Scripts文件夹

② 右键 → Create → C# Script

③ 新脚本以蓝色图标出现,名称处于可编辑状态

④ 输入脚本名称(如"MyFirstScript"),按回车确认

方式二:Assets菜单

Assets → Create → C# Script

方式三:GameObject的Add Component菜单

① 选中GameObject

② Inspector底部 → Add Component

③ 输入"New Script"

④ 点击"New Script",输入脚本名称

💡 第三种方式会同时在Project窗口的Assets根目录创建脚本,并自动将其挂载到选中的GameObject上。

2.2 脚本命名规范

⚠️ C#脚本的命名有几个重要规则:

文件名与类名必须一致:创建的脚本文件名为"MyFirstScript.cs",那么内部的类名也必须是"MyFirstScript"。如果你手动修改了文件名,必须同时修改类名,否则Unity会报编译错误。

使用PascalCase命名法 :每个单词首字母大写,如 PlayerControllerEnemyAIWeaponManager

不使用中文和特殊字符:脚本名只能使用英文、数字和下划线,且不能以数字开头。

名称要有意义 :避免 Script1Test2 这样的无意义命名。好的命名能让人一眼看出脚本的用途。

2.3 打开和编辑脚本

双击脚本文件 :在Project窗口中双击C#脚本文件,Unity会在你配置的代码编辑器中打开它。默认是Visual Studio,你也可以在 Edit > Preferences > External Tools 中更换为Rider或VS Code。

在Inspector中打开:如果脚本已经挂载到GameObject上,选中该物体,在Inspector中点击脚本组件名称右侧的齿轮图标或直接点击脚本名称行,都可以跳转到脚本文件。

三、脚本的基本结构

3.1 默认生成的代码模板

创建新脚本后,Unity会自动生成以下模板代码:

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyFirstScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

让我们逐段理解这个模板:

3.2 using语句

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using 语句相当于"导入命名空间",让你可以使用其他代码库中的类:

  • UnityEngine:Unity引擎的核心命名空间,包含MonoBehaviour、GameObject、Transform、Debug等所有Unity基础类。几乎每个脚本都需要它。
  • System.CollectionsSystem.Collections.Generic:C#标准库的集合类型命名空间,提供List、Dictionary、Queue等数据结构。

3.3 类定义

csharp 复制代码
public class MyFirstScript : MonoBehaviour

这行代码定义了一个名为MyFirstScript的类,它继承自MonoBehaviour

public:访问修饰符,表示这个类可以被其他代码访问。

class MyFirstScript:定义类名。

: MonoBehaviour:继承关系。MonoBehaviour是Unity中所有脚本组件的基类。继承MonoBehaviour后,你的类才能被挂载到GameObject上,才能使用Start、Update等生命周期方法。

3.4 Start方法

csharp 复制代码
void Start()
{
    // 初始化代码
}

Start是Unity生命周期中的一个方法,在脚本实例被启用后、第一次Update之前调用。它只被调用一次,适合用于初始化------获取组件引用、设置初始变量值、建立初始状态等。

3.5 Update方法

csharp 复制代码
void Update()
{
    // 每帧执行的代码
}

Update在游戏的每一帧都会被调用。它是游戏逻辑的核心方法------输入检测、移动更新、状态检查等需要持续执行的逻辑都放在Update中。

四、将脚本挂载到GameObject

4.1 挂载的方式

方式一:拖拽(最常用)

将脚本从Project窗口拖到Hierarchy中的GameObject上,或拖到Scene视图中的物体上。

方式二:拖到Inspector

选中GameObject,将脚本从Project窗口拖到Inspector的空白区域(组件列表下方)。

方式三:Add Component按钮

① 选中GameObject

② Inspector底部 → Add Component

③ 搜索脚本名称

④ 点击添加

方式四:代码中动态添加

csharp 复制代码
gameObject.AddComponent<MyFirstScript>();

4.2 验证脚本挂载成功

脚本成功挂载到GameObject后,在Inspector中可以看到脚本作为一个组件出现:

  • 组件名称显示为脚本的类名
  • 脚本名称左侧有启用/禁用复选框
  • public变量显示在Inspector中,可直接编辑
  • 如果有SerializeField标记的private变量也会显示

4.3 一个物体可以有多个脚本

同一个GameObject上可以挂载任意数量的脚本组件,每个脚本独立运作:

复制代码
Player
├── Transform
├── MeshRenderer
├── Rigidbody
├── PlayerController(处理输入和移动)
├── HealthComponent(管理生命值)
├── WeaponComponent(管理武器)
└── AnimationController(管理动画)

五、编写第一个脚本------让物体旋转

5.1 创建Rotator脚本

让我们写一个最简单的脚本:让物体不停地旋转。

csharp 复制代码
using UnityEngine;

public class Rotator : MonoBehaviour
{
    // 旋转速度,可在Inspector中调整
    public float rotationSpeed = 30f;
    
    void Update()
    {
        // 每帧绕Y轴旋转
        // Time.deltaTime使旋转速度与帧率无关
        transform.Rotate(Vector3.up * rotationSpeed * Time.deltaTime);
    }
}

5.2 代码解析

public float rotationSpeed = 30f

  • public关键字让这个变量在Inspector中可见可编辑
  • float是浮点数类型
  • rotationSpeed是变量名
  • = 30f设置默认值

transform.Rotate(...)

  • transform是当前脚本所在GameObject的Transform组件引用
  • Rotate是Transform的一个方法,让物体旋转
  • Vector3.up是Y轴正方向的简写(即(0,1,0))
  • * rotationSpeed乘以旋转速度
  • * Time.deltaTime乘以帧间隔时间,使旋转速度与帧率无关

5.3 测试脚本

① 创建一个Cube

② 将Rotator脚本拖拽到Cube上

③ 点击Play按钮

④ 观察Cube在Scene视图和Game视图中旋转

⑤ 在Inspector中修改rotationSpeed的值(如改为100),观察旋转速度变化

⑥ 把Vector3.up改为new Vector3(1,1,0),观察旋转方向的变化

✅ 恭喜!你刚刚完成了第一个Unity脚本,让一个物体在你的代码控制下动了起来!

六、让物体动起来------移动脚本

6.1 键盘控制移动

csharp 复制代码
using UnityEngine;

public class SimpleMover : MonoBehaviour
{
    public float moveSpeed = 5f;
    
    void Update()
    {
        // 获取水平输入(A/D键或左右方向键)
        float horizontal = Input.GetAxis("Horizontal");
        // 获取垂直输入(W/S键或上下方向键)
        float vertical = Input.GetAxis("Vertical");
        
        // 构建移动方向向量
        Vector3 movement = new Vector3(horizontal, 0, vertical);
        
        // 移动物体
        transform.Translate(movement * moveSpeed * Time.deltaTime);
    }
}

6.2 Input.GetAxis解析

Input.GetAxis("Horizontal") 从Unity的输入管理器获取"Horizontal"轴的值。这个值在-1到1之间平滑过渡:

  • 按A键或左方向键:值逐渐变化到-1
  • 按D键或右方向键:值逐渐变化到1
  • 不按键:值逐渐回到0

"Vertical"轴对应W/S或上下方向键。

平滑过渡意味着物体不会"突然启动突然停止",而是有一个自然的加速和减速过程------这就是你在游戏中感受到的"手感"。

6.3 跳跃功能

csharp 复制代码
using UnityEngine;

public class PlayerMover : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float jumpForce = 10f;
    
    private Rigidbody rb;
    
    void Start()
    {
        // 获取Rigidbody组件引用
        rb = GetComponent<Rigidbody>();
    }
    
    void Update()
    {
        // 水平移动
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        Vector3 movement = new Vector3(horizontal, 0, vertical);
        transform.Translate(movement * moveSpeed * Time.deltaTime);
        
        // 跳跃
        if (Input.GetKeyDown(KeyCode.Space))
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }
    }
}

⚠️ 使用Rigidbody实现跳跃,需要在GameObject上添加Rigidbody组件。另外,上述代码没有做"在地面上才能跳"的判断------玩家可以无限在空中跳。后续章节会添加地面检测来完善。

七、脚本的调试

7.1 使用Debug.Log输出信息

当你的脚本行为不符合预期时,第一件事就是在关键位置添加Debug.Log输出:

csharp 复制代码
void Start()
{
    Debug.Log("脚本已启动!");
    Debug.Log($"物体的初始位置是:{transform.position}");
}

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log("玩家按下了空格键!");
    }
}

输出的信息会显示在Console窗口中。不同级别的日志:

  • Debug.Log("信息"):普通白色消息
  • Debug.LogWarning("警告"):黄色警告消息
  • Debug.LogError("错误"):红色错误消息

7.2 常见编译错误

"; expected":某行代码末尾缺少分号。

"does not contain a definition":调用了不存在的方法或访问了不存在的属性。可能是拼写错误或缺少using。

"cannot convert":类型不匹配。例如把string赋值给int。

"The name 'xxx' does not exist":使用了未定义的变量。

遇到错误时,双击Console窗口中的错误消息,Unity会直接打开对应的脚本并跳转到出错行号。

八、脚本文件管理

8.1 推荐的文件组织

复制代码
Assets\Scripts\
├── Player\
│   ├── PlayerController.cs
│   ├── PlayerHealth.cs
│   └── PlayerInput.cs
├── Enemies\
│   ├── EnemyAI.cs
│   └── EnemyPatrol.cs
├── Managers\
│   ├── GameManager.cs
│   └── AudioManager.cs
├── UI\
│   ├── MainMenu.cs
│   └── HealthBar.cs
└── Utils\
    ├── ObjectPool.cs
    └── Singleton.cs

8.2 脚本重命名

⚠️ 重命名脚本要小心!在Project窗口中重命名脚本文件后,必须打开脚本文件同步修改类名。文件名和类名必须一致。

如果只修改了文件名而没改类名,Unity会显示错误:"Script class does not match file name"。

九、本篇总结

✅ 本文核心知识点回顾:

  • C#脚本在Unity中是一种特殊的Component,继承自MonoBehaviour
  • 脚本文件名必须与内部的类名一致
  • Start()在脚本启用后调用一次(初始化),Update()每帧调用(持续逻辑)
  • public变量自动显示在Inspector中,可实时编辑
  • transform是脚本所在GameObject的Transform组件的快捷引用
  • Input.GetAxis()获取平滑的输入值,Input.GetKeyDown()检测单次按键
  • Time.deltaTime让移动速度与帧率无关
  • Debug.Log()在Console窗口输出调试信息

📝 下一篇文章将深入讲解Start与Update方法------Unity脚本生命周期的初步探索。

动手任务

① 创建一个Rotator脚本让物体自转

② 创建一个Mover脚本用键盘控制物体移动

③ 修改rotationSpeed和moveSpeed观察Inspector变量控制的效果

④ 使用Debug.Log输出物体的实时位置


关于作者:拥有多年Unity开发经验的游戏开发者,专注Unity系统化教学与最佳实践分享。

相关推荐
花落人散处1 小时前
CDiskClean 开发历程——文件&进程实时监控-实现方案参考
c#
小德车机导航3 小时前
【资源编号:317】高德车机版 9.5.0.60006
教程·技术
达子6664 小时前
第30章_综合案例:HarmonyOs开发图解之 俄罗斯方块游戏
游戏·华为·harmonyos
猿长大人4 小时前
C# | MediatR 入门指南:后端架构解耦
分布式·后端·架构·c#·.net
回忆2012初秋5 小时前
C# 中的 EAP:基于事件的异步编程全面指南(一)
开发语言·c#
曹牧6 小时前
C#:Type
开发语言·c#
用户3721574261356 小时前
C# 如何在 Excel 中创建下拉列表:3 种常见数据源实现方式
c#
czhc11400756637 小时前
工业视觉检测中的通用设计模式与技术笔记
c#