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

文章目录

  • 前言
  • 一、脚本模版及其拓展
    • 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;
#endifpublic 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;
#endifpublic 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;
#endifpublic 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.mzph.cn/bicheng/3471.shtml

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

相关文章

【信安评估】2024年全国职业院校技能大赛高职组“信息安全管理与评估”安徽省选拔赛赛项规程

培训、环境、资料、考证 公众号:Geek极安云科 网络安全群:624032112 网络系统管理群:223627079 网络建设与运维群:870959784 移动应用开发群:548238632 极安云科专注于技能提升,赋能 2024年广东省高校的技…

Centos的一些基础命令

CentOS是一个基于开源代码构建的免费Linux发行版,它由Red Hat Enterprise Linux (RHEL) 的源代码重新编译而成。由于 CentOS是基于RHEL构建的,因此它与RHEL具有非常类似的特性和功能,包括稳定性、安全性和可靠性。并且大部分的 Linux 命令在C…

sqlplus / as sysdba登陆失败,(ORA-01017)

周一上班检查alert log,看到某个库报出大量的错误 提示无法连接到ASM实例,这是某知名MES厂商DBA创建的11G RAC刚刚​转交到我手上的,这又是给我挖了什么坑? 报错为ORA-01017​用户名密码不对?​what? 登陆o…

大语言模型在研究领域的应用——信息检索中的大语言模型

信息检索中的大语言模型 大语言模型提升信息检索任务利用大语言模型进行信息检索大语言模型增强的信息检索模型.检索增强的大语言模型输入优化策略.指令微调策略.预训练策略.总结应用建议未来方向大语言模型对于传统信息检索技术与应用范式带来了重要影响。这两者在技术路径上具…

在Mac M1笔记本上跑大语言模型llama3的4个步骤?(install、pull、run、ask)

要点 Ollama一个功能强大的本地大语言模型LLM运行工具,支持很多模型,并且操作极其简单快速回忆步骤: 下载ollama工具:https://ollama.com/download 下载模型:ollama pull llama3 #根据libs列表直接指定名字 运行模型…

卡巴斯基plus(kaspersky plus) 21.16主界面出不来

请选择下载x86版本的dotnet 6.0 x86版本的dotnet 6.0 https://download.visualstudio.microsoft.com/download/pr/4aded178-a52a-4fcc-a779-59bb444df048/67924e3556a3a69da09528bd74dca9ef/dotnet-sdk-6.0.421-win-x86.exe

企业微信hook接口协议,ipad协议http,发送大视频文件

发送大视频文件 参数名必选类型说明uuid是String每个实例的唯一标识,根据uuid操作具体企业微信send_userid是long要发送的人或群idisRoom是bool是否是群消息 请求示例 {"uuid":"1688853790xxx", //uuid 默认随机生成如果初始化传了id则用初始…

软考-论文写作-论架构风格论文

题目 素材 框架 一、 摘要 2020年12月,我参加了某省政协委员履职系统的开发。该系统为政协机关人员线上开展各项工作以及委员完成各项履职提供了全方位的软件支撑。我在该项目重担任系统架构师一职,负责履职系统的架构设计。本文结合实践,以委员履职系统为例,主要讨论软件…

12.6.1 实验5:IOS恢复

1、实验目的 通过本实验可以掌握: copy方式恢复IOS的步骤。TFTPDNLD方式恢复IOS的步骤。Xmodem方式恢复IOS的步骤。 2、实验拓扑 路由器IOS恢复的实验拓扑如下图所示。 3、实验步骤 如果工作中不慎误删除路由器IOS,或者升级了错误版本的IOS&#xff…

请编写一个函数void fun(char*ss),其功能是:将字符串ss中所有下标为奇数位置上的字母转换为大写(若该位置上不是字母,则不转换)。

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法完整代码和详细的解析。 题干 请编…

制作一个RISC-V的操作系统十三-抢占式多任务和兼容协作式多任务

文章目录 强占式多任务流程代码具体流程兼容协作式多任务(软中断)寄存器 msip流程代码结果 强占式多任务 流程 抢占式多任务由计时器中断触发,最后在处理程序中切换到下一个进程 代码具体流程 上下文中增加pc寄存器 寄存器保留上下文和切…

数据挖掘实验一

一、实验环境及背景 使用软件: Anaconda3 Jupyter Notebook 实验内容: 1.使用Tushare或者其他手段获取任意两支股票近三个月的交易数据。做出收盘价的变动图像。2.使用Pandas_datareader获取世界银行数据库中美国(USA)、瑞典&…

【中级软件设计师】上午题12-软件工程(2):单元测试、黑盒测试、白盒测试、软件运行与维护

【中级软件设计师】上午题12-软件工程(2) 1 系统测试1.1 单元测试1.2 集成测试1.2.1 自顶向下1.2.2 自顶向上1.2.3 回归测试 2 测试方法2.1 黑盒测试2.1.1 McCabe度量法 2.2 白盒测试2.2.1 语句覆盖-“每个流程”执行一次2.2.2 判定覆盖2.2.3 条件覆盖-A…

vue+springboot项目的登录验证码(JAVA自带)

后台springboot CaptureController package com.example.controller;import com.example.common.Result; import com.example.service.AuthCodeService; import com.example.utils.CodeUtils; import lombok.SneakyThrows; import org.apache.ibatis.annotations.Param; impo…

Java openrasp记录-01

例子1 https://github.com/anbai-inc/javaweb-expression 一个hook ognl、spel、MVEL表达式注入的例子 用的是asm5进行字节码修改 采用premain进行插桩,重写transform方法 expClassList是要hook的类,这里定义在MethodHookDesc 这里判断hook点通过类名…

Java并发编程:ThreadPoolExecutor详细源码解析与应用

Thread直接创建线程的弊端 在开始解析ThreadPoolExecutor类之前,让我们先来了解直接创建线程所带来的弊端。在Java中,线程是资源密集型对象,每当需要并发执行任务时,直接创建新线程会带来以下问题: 资源消耗 每个线…

贪吃蛇身子改进加贪吃蛇向右移动

1. 蛇移动的思想: 其实就是删除头节点 ,增加尾节点;一句代码搞定 struct Snake *p; p head; head head -> next; free(p) 防止造成多的空间节点 2.增加尾节点代码思想: 2.1 .开辟new 节点的空间 struct Snake *new (stru…

解决Android studio更换sdk地址后flutter项目显示no device selected

问题描述 因为之前sdk的路径在c盘上,经常在更新或下在sdk后c盘饱满,于是就更换了sdk的路径,更换sdk路径后就导致flutter项目在选择设备的时候出现no device selected 找不到设备,但是在device Manager可以看到物理设备或者是虚拟…

Java设计模式:使用责任链模式和状态模式优化‘审批流程‘

Java设计模式:使用责任链模式和状态模式优化审批流程 摘要引言 需求流程图正文内容📐 基本概念介绍 功能实现示例1:设计模式:责任链模式方法:好处: 示例2:设计模式:责任链模式方法和操作流程:好…

【canvas】前端创造的图片粒子动画效果:HTML5 Canvas 技术详解

前端创造的图片粒子动画效果:HTML5 Canvas 技术详解 我们将深入探讨如何通过 HTML5 的 Canvas 功能,将上传的图片转换成引人入胜的粒子动画效果。这种效果将图片分解成小粒子,并在用户与它们交互时产生动态变化。我们将分步骤详细解析代码&a…