Unity读书系列《Unity3D游戏开发》——脚本(一)

news2024/11/27 4:18:10

文章目录

  • 前言
  • 一、脚本模版及其拓展
    • 1、脚本模版
    • 2、拓展脚本模版
  • 二、脚本的生命周期
  • 三、脚本的执行顺序
  • 四、脚本序列化
    • 1、序列化数据
    • 2、serializedObject
    • 3、监听部分元素修改事件
  • 五、定时器与间隔定时器
  • 六、工作线程(多线程)
  • 总结


前言

脚本在Unity的重要程度不用多说,她是大部分软件的核心组件。
我们将在此篇文章学习脚本模版及其拓展、脚本的生命周期、脚本的执行顺序、脚本序列化,下一篇为脚本编译与调试。


一、脚本模版及其拓展

1、脚本模版

如下图我们可以在Project视图右键进行脚本创建,除了C#脚本,还有两类脚本;Testing用来做单元测试,Playables是TimeLine引入的新概念。
在这里插入图片描述
通常来讲我们会根据项目修改脚本模版,位置在Unity安装位置的Resource文件夹内,例如:“C:\Program Files\Unity 2021.3.16f1\Editor\Data\Resources\ScriptTemplates”。除了按照项目修改模版,通常会将脚本编码改成UTF-8并在脚本模版中加入中文或中文字符。
在这里插入图片描述

2、拓展脚本模版

如果按上述方法修改脚本模版会十分麻烦,不说每个版本的unity都需要修改,项目里每个成员都需要修改,当模版变动难道每个人都要重新修改吗。我们想做到版本管理可以拓展脚本的方式添加模版。

二、脚本的生命周期

Unity脚本有一套完整的生命周期,无需手动调用。其中包含初始化、更新回调、渲染、销毁,我们经常使用的协程等也在其内。
官方解释:
在这里插入图片描述
书中解释:
在这里插入图片描述

三、脚本的执行顺序

在上一章中当有两个脚本标记了"[CustomEditor(typeof(Camera))]",只会执行第一个创建的脚本逻辑。
为什么呢?Unity的脚本可以预先挂载场景中,也可以在运行时动态添加,所以用Script Execution Order使用来管理脚本的执行顺序,我们可以在此添加脚本并设置顺序。
在这里插入图片描述
我们考虑一件事,现在有多个脚本,A脚本在Awake获取B脚本的数据,A如果比B先执行那就会报错。实际上这种时序的问题还会发生在项目越发复杂,初始化过多的情况。不仅如此,多个脚本还会产生多余消耗,假设每个脚本都有初始化(Awake、Start等)和更新(Update)的方法,几百个脚本同时运行,性能差的主机可能分分钟卡死。
解决方法:将系统分类,每个系统的初始化等功能都设置入口,功能统一调用。初学者推荐尝试单例的写法来管理小项目,再根据项目尝试工厂模式、适配器模式等设计模式,最后学习框架的思想。

四、脚本序列化

想了解脚本序列化,首先我们需要明白脚本本身并没有保存数据,而是将数据保存于文件中,也就是脚本可以通过序列化和反序列化来保存游戏。
书中举例,给场景其中一个物体加上脚本Test.cs,再找一个预制体Prefab.prefab加上脚本Test.cs。接下来我们修改场景中的脚本数据,也就是Id,那么数据将保存在Scene.unity;同理,在Project下修改预制体上的脚本Id,那么数据会保存在预制体文件夹内。

如果把预制体赋值到场景的脚本中(脚本中的public GameObject prefab;),那么数据会存在Scene.unity。大家仔细想想,平常雀氏是这样操作的,只是不明所以罢了。

public class Test : MonoBehaviour
{
	public int Id;
	public GameObject prefab;
}

1、序列化数据

打开上面的预制体和场景,就会发现里面存着序列化的数据,这里不做展示。
通常,公开的对象会支持序列化格式,如果不想显示可以加上[HideInInspector],私有序列化需要再代码上加上[SerializeField]。

public class Test : MonoBehaviour
{
	[SerializeField]
	private int Id;
	[SerializeField]
	private GameObject prefab;
}

假如我此时还想访问呢,直接请出serializedObject.FindProperty()访问私有属性。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class Script_04_08 : MonoBehaviour
{
    [SerializeField]
    private int id;
    [SerializeField]
    private string name;
    [SerializeField]
    private GameObject prefab;
}

#if UNITY_EDITOR
[CustomEditor(typeof(Script_04_08))]
public class ScriptInsector : Editor
{
    public override void OnInspectorGUI()
    {
        //更新最新数据
        serializedObject.Update();
        //获取数据信息
        SerializedProperty property = serializedObject.FindProperty("id");
        //赋值数据
        property.intValue = EditorGUILayout.IntField("主键", property.intValue);

        property = serializedObject.FindProperty("prefab");
        property.objectReferenceValue = EditorGUILayout.ObjectField("游戏对象",
            property.objectReferenceValue,typeof(GameObject),true);

        //全部保存数据
        serializedObject.ApplyModifiedProperties();
    }
}
#endif

2、serializedObject

serializedObject只能在Editor中使用,它专门用于获取设置的序列化信息。通常,要开发复杂的编辑组件,都需要重写OnInspectorGUI()方法,但是如果希望有些用源生的绘制结构,同时兼容有些自定义渲染的话,那该怎么办呢?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class SerializedObjectTest : MonoBehaviour
{
    [SerializeField]
    private int id;
    [SerializeField]
    private GameObject[] targets;
}

#if UNITY_EDITOR
[CustomEditor(typeof(SerializedObjectTest))]
public class ScriptInsector : Editor
{
    public override void OnInspectorGUI()
    {
        //更新最新数据
        serializedObject.Update();
        //获取数据信息
        SerializedProperty property = serializedObject.FindProperty("id");
        //赋值数据
        property.intValue = EditorGUILayout.IntField("主键", property.intValue);
        //以默认样式绘制数组数据
        EditorGUILayout.PropertyField(serializedObject.FindProperty("targets"), true);
        //全部保存数据
        serializedObject.ApplyModifiedProperties();
    }
}
#endif

效果如下:
在这里插入图片描述

3、监听部分元素修改事件

脚本面板中,参与绘制的元素都是在OninspectorGUI中绘制的。我们想监听其中的一个元素有两种方法,第一种适用于简单的脚本,在脚本中写入Onvalidate(),当面板信息发生改变就会回调该方法;

void Onvalidate(){
Debug.log("信息改变");
}

第二种需要监听GUI的元素写在EditorGUI.BeginChangeCheck()。我们监听变化则需要在if(EditorGUI.EndChangeCheck()) 中处理。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class Test : MonoBehaviour
{
    [SerializeField]
    private GameObject[] targets;
}

#if UNITY_EDITOR
[CustomEditor(typeof(Test))]
public class ScriptInsector : Editor
{
    public override void OnInspectorGUI()
    {
        //更新最新数据
        serializedObject.Update();
        //标记检查
        EditorGUI.BeginChangeCheck();
        EditorGUILayout.PropertyField(serializedObject.FindProperty("targets"), true);
        //标记检查发生变化
        if(EditorGUI.EndChangeCheck()) {
            Debug.Log("元素发生变化");
}
        //判断面板元素是否任意发生改变
        if(GUI.changed) {

        }
        //全部保存数据
        serializedObject.ApplyModifiedProperties();

    }
}
#endif

五、定时器与间隔定时器

通常我们可以用协程做定时器,缺陷是依赖于脚本,所以封装一个不依赖脚本实现的定时器是很有必要的。
详细使用请看定时器与间隔定时器。

六、工作线程(多线程)

工作线程(多线程)是指在一个程序中同时执行多个任务的能力。多线程编程可以提高程序的性能和响应性,特别是在需要同时执行多个任务的情况下。工作线程通常用于执行耗时的任务,以避免阻塞主线程,从而保持程序的流畅性。
目前很多主流游戏或软件在启动或下载等待时会使用多线程技术,应用十分广泛。
详细使用请看Unity多线程。


总结

这篇文章将介绍Unity中脚本的核心概念和重要性。我们探讨如何创建和定制脚本以满足特定需求,以及脚本的生命周期、执行顺序和序列化等内容。后面两个示例(定时器和工作线程的运用)我分别用单独的章节说明,如果需要再去学习运用;这种安排旨在强调项目驱动的学习方式,同时鼓励读者在实践中运用这些示例来更快地提升自己的技能。逐步学习并根据需求应用所学知识,将使读者能够更有效地掌握相关技能。
最后,感谢大家观看,欢迎讨论指正错误,别忘了点赞👍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1625676.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中颖51芯片学习9. PWM(12bit脉冲宽度调制)

中颖51芯片学习9. PWM(12bit脉冲宽度调制) 一、资源简介二、PWM工作流程三、寄存器介绍1. PWMx控制寄存器PWMxCON2. PWM0周期寄存器PWM0PH/L3. PWM1周期寄存器PWM1PH/L4. PWM0占空比控制寄存器PWM0DH/L5. PWM1占空比控制寄存器 PWM1DH/L6. 占空比寄存器与…

临床常用的8个护理评估量表分享,医护必备!

常笑医学整理了8个常用的护理评估量表,包括Morse跌倒量表、Braden压疮评分、格拉斯哥昏迷评分GCS、深静脉血栓评分DVT、Brathel日常生活活动能力量表等,这些量表在常笑医学网上均支持在线使用和下载,供医护人员学习与使用。 Morse跌倒危险因素…

【北京迅为】《iTOP龙芯2K1000开发指南》-第三部分 迅为龙芯开发板快速体验

龙芯2K1000处理器集成2个64位GS264处理器核,主频1GHz,以及各种系统IO接口,集高性能与高配置于一身。支持4G模块、GPS模块、千兆以太网、16GB固态硬盘、双路UART、四路USB、WIFI蓝牙二合一模块、MiniPCIE等接口、双路CAN总线、RS485总线&#…

webpack热更新原理详解

文章目录 前言基础配置创建项目HMR配置 HMR交互概览HMR流程概述HMR实现细节初始化注册监听编译完成事件启动服务监听文件代码变化服务端发送消息客户端收到消息热更新文件请求热更新代码替换 问题思考 前言 刷新分为两种:一种是页面刷新,不保留页面状态…

LANGUAGE-DRIVEN SEMANTIC SEGMENTATION

环境不易满足,不建议复现

CentOS7利用宝塔面板安装zabbix6.0.x详细安装教程(手把手图文详解版)

最近学习CentOS7安装zabbix6.0.x的版本,尝试了很多教程,很多都比较麻烦且容易出错,最后发现使用宝塔面板最为简单,将具体过程记录下来,一来分享给有需要的人,二来自己也当记录笔记,以免以后遗忘…

Hive中几个非常重要的问题

1、Hive 有哪些方式保存元数据,各有哪些优缺点 (1).DerBy数据库:默认自带 优点:使用简单,不需要额外的配置。 缺点:只有一个客户端,多个客户访问会报错。 (2).使用MySql数据库存储 优点:单独的…

OSPF的LSA详解

一、什么是LSA?LSA作用? 在OSPF协议中,LSA全称链路状态通告,主要由LSA头部信息(LSA摘要)和链路状态组成。部分LSA只有LSA头部信息,无链路状态信息。使用LSA来传递路由信息和拓扑信息&#xff0c…

linux系统安全

一、账号安全基本措施 1.1 系统账号清理 1.1.1 将用户设置为无法登录-- 改登录shell 登录shell是用户与计算机系统直接交互的接口,使用户能够通过命令行方式进行各种操作和管理。 所以让用户无法登录,其实就是将登录shell改为 /sbin/nologin,可以用us…

移动应用安全

移动应用安全 移动应用安全主要关注Android、iOS、Windows Phone等平台上移动应用软件安全状态。它涉及应用程序在其设计运行的平台上下文中的安全问题、它们使用的框架以及预期的用户集。所有主流的移动平台都提供大量可选的安全控制,旨在帮助软件开发人员构建安全…

面试官问如何实现二级缓存怎么进行回答以及延伸出更多知识点呢?

二级缓存的优势与缺点 优点: 1)二级缓存相比只调用一层 Redis 缓存,访问速度更快。对于一些不经常修改的数据而查询十分频繁的可以直接放在本地缓存(一级)里面。 作为面试者的扩展延伸:我在本地缓存的实…

【MySQL 数据宝典】【索引原理】- 002 示例+逐个字段学明白 Explain

一、Explain 概述 使用 EXPLAIN 关键字可以模拟优化器来执行SQL查询语句,从而知道MySQL是如何处理我们的SQL语句的。分析出查询语句或是表结构的性能瓶颈。 1.1 MySQL 查询过程 通过explain我们可以获得以下信息: 表的读取顺序数据读取操作的操作类型…

华为ensp中链路聚合两种(lacp-static)模式配置方法

作者主页:点击! ENSP专栏:点击! 创作时间:2024年4月26日11点54分 链路聚合(Link Aggregation),又称为端口聚合(Port Trunking),是一种将多条物理…

OU和域用户的创建

OU和域用户的创建 导航 文章目录 OU和域用户的创建导航一、创建ou二、创建用户三、验证 一、创建ou 在服务器管理器里面点击右上角的工具,选择Active Directory 用户和计算机右击我们的域,选择新建,选择组织单位,并填入我们的单位名字 二、创建用户 右击我们刚刚新建的组织…

prompt提示词:AI英语词典优化版Pro,让AI教你学英语,通过AI实现一个网易有道英语词典

目录 一、前言二、效果对比三、优化《AI英语词典》提示词四、其他获奖作品链接 一、前言 不可思议!我的AI有道英语字典助手竟然与百度千帆AI应用创意挑战赛K12教育主题赛榜首作品差之毫厘 ,真的是高手都是惺惺相惜的,哈哈,自恋一…

pytest参数化数据驱动(数据库/execl/yaml)

常见的数据驱动 数据结构: 列表、字典、json串 文件: txt、csv、excel 数据库: 数据库链接 数据库提取 参数化: pytest.mark.parametrize() pytest.fixture()…

Stable Diffusion WebUI 使用 VAE 增加滤镜效果

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 大家好,我是水滴~~ 本文主要介绍 VAE 模型,主要内容有:VAE 模型的概念、如果下载 VAE 模型、如何安装 VAE 模型、如…

苍穹外卖学习

并不包含全部视频内容&#xff0c;大部分都按照操作文档来手搓代码&#xff0c;资料&#xff0c;代码都上传git。 〇、实际代码 0.1 Result封装 package com.sky.result;import lombok.Data;import java.io.Serializable;/*** 后端统一返回结果* param <T>*/ Data pub…

【EP2C35F672C8 EDA试验箱下载 38译码器实现】

文章目录 前言一、实验设备1.实验箱2.下载器&#xff1a; 二、编译工程1.编译工程2.添加tcl引脚配置文件2.1将tcl文件拷贝到工程目录下&#xff1a;2.2 在软件中添加tcl文件 3.tcl文件简答讲解 三、下载四、实验结果总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内…

【LeetCode:2095. 删除链表的中间节点 + 链表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…