Untiy基础学习(三)Untiy中编写脚本的基本规则

一、怎么创建脚本

在Project窗口下,右键Create C#Script 即可创建脚本

创建脚本的注意事项 :

1)类名和文件名必须一致,不然不能挂载(因为反射机制创建对象,会通过文件名去找Type)

2)没有特殊需求 不用管命名空间

3)创建的脚本默认继承MonoBehavior

4)可以放在Assets文件夹下的任何位置(建议同一文件夹管理)

二、关于MonoBehavior的介绍

        首先它是一个基类,任何生命周期函数的执行都需要直接或者间接继承这个类,至于生命周期函数是是什么,我们后面讲。所有 Unity 脚本若需要与引擎生命周期事件(如初始化、更新、销毁等)交互,必须直接或间接继承 MonoBehaviour。这是 Unity 设计的基础规则,只有继承此类的脚本才能被引擎识别为“组件”,从而挂载到 GameObject 上并参与游戏逻辑的驱动。它有以下特点:

        ①创建的脚本基本都默认继承MonoBehavior 继承了它才能够挂载在GameObject上。因为Unity 通过继承 MonoBehavior 的类来标记其为“可挂载组件”。Unity 编辑器会扫描脚本是否继承自 MonoBehavior ,只有符合条件的脚本才会出现在“Add Component”菜单中。
        ②继承了MonoBehavior的脚本不能new 只能挂!!!!!!!!继承 MonoBehaviour 的脚本 不能手动实例化如 MyScript script = new MyScript();)。因为Unity 要求组件必须依附于 GameObject而 new 创建的实例未绑定任何对象,无法被引擎管理。生命周期函数(如 AwakeUpdate)由引擎自动触发,未挂载的脚本不会执行这些逻辑。

        ③继承了MonoBehavior的脚本不要去写构造函数,因为我们不会去new它,写构造函数没有任何意义。Unity 不会调用 MonoBehaviour 的构造函数,初始化逻辑应由 Awake 或 Start 实现。构造函数可能在非预期时机执行(如编辑器加载时),导致不可控行为。等后面学习了生命周期函数,就知道一般是使用Awake和Start进行初始化了。

        ④继承了MonoBehavior的脚本可以在一个对象上挂多个(如果没有加DisallowMultipleComponent特性)例如,为敌人挂载多个“攻击效果”脚本,每个脚本控制不同的攻击逻辑。或为 UI 元素挂载多个“动画控制器”脚本,分别处理不同状态的动画。

        ⑤继承MonoBehavior的类也可以再次被继承,遵循面向对象继承多态的规则。MonoBehaviour 的子类可以进一步被继承,遵循面向对象的基本原则。子类可以重写父类的生命周期方法(如 Update),并通过 base.Method() 调用父类逻辑。当然这些都是后话。

了解小知识:为什么会这样设计呢?

组件化开发

        每个脚本代表一个独立功能模块,通过组合不同组件构建复杂对象(如角色 = 移动组件 + 动画组件 + 攻击组件)。

        避免“上帝脚本”(一个脚本处理所有逻辑),提升代码可维护性。

引擎控制权

        Unity 引擎完全掌控组件的生命周期(如创建、更新、销毁),开发者只需填充逻辑,无需手动管理内存或执行顺序。

事件驱动模型

        通过生命周期方法和事件回调(如 OnCollisionEnter)响应游戏状态变化,而非传统的主循环控制。

三、关于不继承Mono的类

        ①不继承MonoBehavior的类 不能挂载在GameObject上。因为上面提到了,Unity 编辑器通过反射检查脚本是否继承 MonoBehaviour,只有符合条件的类才会出现在“Add Component”菜单中,只有继承了的才有组件成为权!
        ②不继承MonoBehavior的类 想怎么写就怎么写 如果要使用需要自己new。非 MonoBehaviour 类本质是普通的 C# 类,不依赖 Unity 的组件系统,因此:

  • 无需遵循 Unity 的约束:可以随意定义构造函数、静态方法或字段。

  • 实例化方式:必须通过 new 关键字手动创建对象(如 MyClass obj = new MyClass();)。

        ③不继承MonoBehavior的类一般是单例模式的类(用于管理模块,全局管理游戏状态、资源、配置等。)或者数据结构类(用于存储数据,纯粹用于存储和操作数据。)
        ④不继承MonoBehavior的类 不用保留默认出现的那几个函数。因为Unity 的生命周期方法(如 AwakeUpdate)是 MonoBehaviour 提供的特性。非 MonoBehaviour 类不具备这些功能,因此:无需保留默认函数:如 Start 或 Update 不会被 Unity 调用,定义它们无意义。

四、关于脚本的执行先后顺序

五、默认脚本内容

        你有没有每次发现我们创建的脚本都长得一样,这是因为Untiy自己配置了模版,当然,这模版它Untiy配的,我们就配不得吗,走,我们去看看在哪里配置。 

首先:先得来到这个Untiy hub中,点击这个在资源管理器中查看

然后走这个路径:就可以看到很多很多的txt文件,这些就是模版文件

 不建议自己随意修改 

来来来,做几道题目练练手!!

问题一:MonoBehaviour 的构造函数问题

        在 Unity 中,为什么继承 MonoBehaviour 的脚本不应定义构造函数?如果在构造函数中初始化变量,可能会导致什么问题?

        参考答案:Unity 不会调用 MonoBehaviour 的构造函数,初始化逻辑应由 Awake 或 Start 完成。构造函数可能在编辑器模式下意外触发(如脚本重新编译时),导致不可控行为。

        可能存在的问题:若在构造函数中初始化组件引用(如 GetComponent<T>()),此时 GameObject 可能未完全初始化,导致空引用异常。构造函数中的逻辑可能破坏 Unity 的组件依赖链,引发初始化顺序混乱。

问题二:单例模式的选择

        在 Unity 中,实现单例模式时,为何通常选择不继承 MonoBehaviour 的普通类,而不是通过挂载到 GameObject 的 MonoBehaviour 脚本实现?请比较两种方式的优缺点。

        参考答案:

普通类单例(非 MonoBehaviour)

  • 优点

    无需依赖 GameObject,内存占用更低。

    生命周期完全由代码控制,跨场景时更稳定。

  • 缺点

    无法直接使用 Unity 的生命周期方法(如 Update)。

    需要手动管理初始化和销毁逻辑

MonoBehaviour 单例

  • 优点

    可方便使用 Unity 生命周期方法(如 Awake 初始化)。

    可在 Inspector 中配置公开变量。

  • 缺点

    依赖 GameObject,跨场景时需通过 DontDestroyOnLoad 防止销毁。

    可能因场景切换或对象失活导致单例失效。

        结论:若单例需要与 Unity 生命周期或场景对象交互(如 UI 管理),使用 MonoBehaviour;若仅需全局逻辑管理(如配置读取),优先使用普通类单例。

问题三:数据类的设计选择

        假设需要设计一个 PlayerData 类,用于存储玩家的血量、等级和装备信息。为什么这个类不应继承 MonoBehaviour?如果需要在 Inspector 中编辑该类的数据,如何实现?

        参考答案:

不继承 MonoBehaviour 的原因

PlayerData 是纯粹的数据容器,无需与 GameObject 绑定或参与 Unity 生命周期。

继承 MonoBehaviour 会引入不必要的开销(如组件内存占用),破坏代码简洁性。

在 Inspector 中编辑数据

        将 PlayerData 声明为可序列化的普通类:

[System.Serializable]  
public class PlayerData {  
    public int health;  
    public int level;  
    public List<string> equipment;  
}  

        在某个 MonoBehaviour 脚本中声明 PlayerData 的字段,即可在 Inspector 中编辑:

public class Player : MonoBehaviour {  
    public PlayerData data;  
}  

这样子就可以了

### 关于Unity中的强化学习 #### 下载并安装ML-Agents工具包 为了开始使用Unity进行强化学习,需先下载ml-agents工具包[^1]。该过程涉及设置Python环境以及克隆GitHub上的官方仓库。 #### 创建适合强化学习的虚拟环境 Unity提供了一套完整的工具集来构建具有高度自定义物理特性的虚拟世界[^2]。这些特性对于设计复杂的训练场景至关重要,因为它们允许开发者精确控制物体的行为方式及其相互作用规律。通过调整参数如重力、摩擦系数等,可以创造出无限可能的学习情境。 #### 使用预设模板快速上手 对于初学者而言,利用现成的例子作为起点是非常有益的做法。例如,在提供的教程里提到的一个流程实例展示了如何一步步建立起自己的第一个基于ML-Agents的游戏AI。这包括但不限于配置项目结构、编写奖励机制脚本等内容。 #### 解决常见问题与优化建议 当尝试集成第方库比如elegant-RL时可能会遇到一些挑战。有报告指出,在某些情况下由于训练和测试阶段采用了不同版本的仿真器而导致兼容性问题发生[^3]。为了避免此类情况的发生,应当确保在整个开发周期内保持一致性的实验条件,并仔细阅读文档以获取最佳实践指导。 ```python import mlagents.trainers as trainers from mlagents_envs.environment import UnityEnvironment # 初始化Unity环境 env = UnityEnvironment(file_name=None) # 加载默认Brain behavior_name = list(env.behavior_specs)[0] def train(): trainer_config = trainers.TrainerFactory.create_trainer(behavior_name, "PPO") while True: env.step() decision_steps, terminal_steps = env.get_steps(behavior_name) # 训练逻辑... ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FAREWELL00075

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值