| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> unity hub 自带教程学习笔记(ruby、lemonJohn) -> 正文阅读 |
|
[游戏开发]unity hub 自带教程学习笔记(ruby、lemonJohn) |
https://learn.unity.com/?_gl=1*1c5ya13*_ga*MTAzODc3MzI4LjE1OTc5MTQ3NzI.*_ga_1S78EFL1W5*MTYyNjM0NTY2MC4xNy4xLjE2MjYzNTM5ODAuNQ..&_ga=2.119106061.528537968.1626154667-103877328.1597914772 1. void OnTriggerEnter2D(Collider2D other){}? ? ? //2d游戏与触发器开始重叠,other内包含与当前触发器碰撞的对象的信息 RubyController controller = other.GetComponent<RubyController>();? //获得触发器碰撞对象中的组件. 添加尖括号的原因是 GetComponent 方法为泛型。泛型方法具有两组不同的参数:普通参数和类型参数。尖括号之间列出的参数是类型参数。 2. 脚本中的public的变量将在unity脚本中显示出来,可进行重载; 3. public int health { get { return currentHealth; } } //让外部获取变量但不可修改的只读函数示例。 4. Rigidbody2D rigidbody2d; horizontal = Input.GetAxis("Horizontal"); 刚体运动 Vector2 position = rigidbody2d.position; 动作表现
在此部分中,如果机器人垂直移动,则会将?0?发送到 horizontal 参数,而 direction 定义机器人是向上还是向下移动。 5. rigidbody2d.MovePosition(position);? //刚体移动 6. currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth); 7. void FixedUpdate()? ? //非每帧更新,每隔一个固定时间更新一次 8. void?OnCollisionEnter2D(Collision2D other)? //刚体与某个对象碰撞时调用的函数 9. Mathf.Approximately(move.x, 0.0f)? ?//类似==,因为计算机存储浮点数的方式意味着精度会有很小的损失。所以,不应测试完美的相等性,因为最终结果应该是?0.0f?的运算可能会得出类似?0.0000000001f?的结果。Approximately?会考虑这种不精确性,如果除去这种不精确性可以认为数值相等,将返回 true。 .Normalize()? //使长度等于1,用在vector2里作为方向储存 .magnitude? ?//计算向量长度 10. GameObject projectileObject = Instantiate(projectilePrefab, rigidbody2d.position + Vector2.up * 0.5f, Quaternion.identity); 四元数 (Quaternion)?是一种可以表达旋转的数学运算符,但这里只需要记住的是,Quaternion.identity?表示“无旋转”。 11. if(transform.position.magmitude >1000.0f)? //position?可以看作是从世界中心到对象所在位置的向量,magnitude?是该向量的长度。因此,position 的 magnitude 就是到中心的距离。 可以获取角色和齿轮之间的距离(使用?Vector3.Distance (a,b)?函数计算?position a?与?position b?之间的距离)。 12. smokeEffect.Stop();? //
烟雾会立即消失。这是因为当粒子系统被销毁时,也会销毁当前正在处理的所有粒子,即使是刚刚创建的粒子。 但?Stop?只会阻止粒子系统创建粒子,已经存在的粒子可以正常结束自己的生命周期。这比所有粒子突然消失要看起来自然得多。 13. 实例化粒子系统 与飞弹一样,从粒子系统制作预制件后,便可以使用?Instantiate 函数创建粒子系统。 因此,对于仅发生一次的效果(例如被击中或拾取生命值可收集对象),你可以将对预制件的引用存储在公共变量中,并在应该产生效果时调用?Instantiate。如果?Particle System?未设置为?Looping?并且?Stop Action?设置为?Destroy,则会播放效果,然后销毁。 14。 originalSize = mask.rectTransform.rect.width;? //获取UI的宽度 mask.rectTransform.SetSizeWithCurrentAnchors(RcctTransform.Axis.Horizontal, originalSize * value);? ?//以当前锚点设置大小 代码行 using?UnityEngine; 让你无需在?UnityEngine?中的所有类(如?GameObject)前面键入?UnityEngine。所以,如果你在?using.UnityEngine; 代码行下面直接添加?using UnityEngine.UI; 代码行,你的代码将会正确编译,因为现在可以在该脚本内直接使用 Image 了。 15. public?class?UIHealthBar?:?MonoBehaviour?{ public static UIHealthBar instance { get; private set; } void?Awake()?{ instance =?this; }
16. if?(Input.GetKeyDown(KeyCode.X)) { RaycastHit2D hit = Physics2D.Raycast(rigidbody2d.position + Vector2.up *?0.2f, lookDirection,?1.5f, LayerMask.GetMask("NPC")); 首先,你将声明一个类型为?RaycastHit2D?的新变量。此变量存储由?Physics2D.Raycast?提供的?Raycast?的结果。 Physics2D.Raycast?有多种版本,但我们在这里使用的版本有四个参数: 你的示例中的起点是从 Ruby 的位置向上偏移,因为你想从 Ruby 精灵中心进行测试,而不是从她的双脚。 方向,这是 Ruby 注视的方向。 射线的最大距离应设置为?1.5,这样射线投射不会测试相距起点?1.5?个单位的相交点。 一个图层遮罩,允许我们仅测试某些图层。在相交测试期间,所有不属于遮罩的图层都将被忽略。在这里,你将选择?NPC 图层,因为该图层包含你的青蛙。 17.? 名称开头的?m_?是什么意思?这是命名约定的一部分。命名约定用于标识特定对象或对象类。在此项目中,您将使用 Unity 的内部命名约定。所有变量均以小写字母开头,但随后的单词以大写字母开头(这称为?camelCase) 例外情况是非公共成员变量,这种变量以 m_ 前缀开头,所有单词均以大写字母开头(这称为?PascalCase)。成员变量是属于类而不是属于特定方法的变量。非公共成员变量的 m_ 部分起源于它们是“成员 (member)”变量。 18.
3D 空间中的矢量具有三个值 — 此?Set?方法为每一个分配一个值。该方法有三个参数,矢量的每个坐标对应一个参数。 移动矢量由两个数字组成,这两个数字的最大值可以为 1。如果它们两者的值都为 1,则矢量的长度(称为其大小)将大于 1。这便是勾股定理描述的三角形的边之间的关系。 这意味着角色沿对角线移动的速度将比沿单个轴的移动速度更快。为了确保不会发生这种情况,您需要确保移动矢量始终具有相同的大小。为此,可对其进行标准化。对矢量进行标准化意味着保持矢量的方向相同,但是将其大小更改为 1。
接下来,使用矢量来获取并存储旋转,以便可以在任何需要的地方使用。存储移动矢量一样存储旋转,因此在该位置声明其变量很合理。
四元数 (Quaternion)?是存储旋转的一种方式,可用于解决将旋转存储为 3D 矢量时遇到的一些问题。本教程不会详细探讨四元数,现在只需要知道它们是一种存储旋转的方式即可。 为 Quaternion 指定默认值 Quaternion.identity。通常情况下,创建类的实例时,会将属于类的变量(成员变量)而不是属于特定方法的变量设置为默认值。例如,Vector3 的默认值是将 x、y 和 z 都设置为 0。四元数也是如此。但是,虽然零矢量是合理的(因为没有移动),零四元数却不太合理。这里设置的 Quaternion.identity 值就是为其赋予无旋转的值,这是一个更合理的默认值。 创建了旋转变量,现在可以对其进行设置。在创建 desiredForward 变量的代码行下面,添加以下行:
该行代码仅调用?LookRotation?方法,并在给定参数的方向上创建旋转。 20. 该角色有一段有趣的 Walk 动画,最好为此使用根运动。但是,该动画中没有任何旋转,如果尝试在 Update 方法中旋转刚体 (Rigidbody),则动画可能会覆盖该刚体(这可能导致角色在应该旋转的时候不旋转)。 实际需要的是动画的一部分根运动,但不是全部的根运动;具体来说,需要应用移动而不是旋转。那么如何更改从 Animator 中应用根运动的方式呢?幸运的是,MonoBehaviour 有一种特殊的方法可用于更改从 Animator 中应用根运动的方式。 在 Update 方法下面,声明一个新方法:
让我们先从移动开始吧。将以下行添加到新的 OnAnimatorMove 方法中:
首先,要使用对 Rigidbody 组件的引用来调用其 MovePosition 方法,并传入唯一的参数:其新位置。新位置从刚体的当前位置开始,然后您在此基础上添加一个更改 — 移动矢量乘以 Animator 的 deltaPosition 的大小。但是,这是什么意思? Animator 的?deltaPosition?是由于可以应用于此帧的根运动而导致的位置变化。将其大小(即长度)乘以我们希望角色移动的实际方向上的移动向量。 21. 以前,查找对组件的引用时,使用的是 GetComponent 方法,但这仅适用于与此脚本在同一游戏对象上的组件。 为 Canvas Group 组件创建一个可以在 Inspector 中分配的公共变量。?在 player 变量声明下面添加以下公共变量声明:
22. 在代码块中添加以下代码行以退出游戏:
这里有一些重要的知识需要了解。该方法确实可以退出游戏,但仅适用于完全构建的应用程序。目前,该游戏只是在 Editor 中播放的一个项目,因此尚无任何作用。 23. 使用 Observer 类来检测玩家的角色。在脚本中的花括号之间,添加以下行:
该脚本将检查玩家角色的?Transform,而不是其游戏对象。这样可以更轻松地了解 JohnLemon 的位置并确定是否可以清楚看到他。 24. 有了方向,接下来便可以创建射线 (Ray)。在 direction 变量下面添加以下代码行:
Unity 中有很多不同的 Raycast 方法,但是所有这些方法都有两个共同点:它们需要定义发生射线投射的射线,以及关于要检测的碰撞体类型的限制。 您将使用的 Raycast 方法会返回一个布尔值,当射线投射击中某个对象时为 true,否则为 false。因为返回的是布尔值,所以将 Raycast 方法放在 if 语句中非常方便。if 语句的代码块仅在射线投射击中某个对象时才执行。 在创建射线 (Ray) 的位置下方,并且仍在之前编写的 if 语句内,添加以下代码:
已经定义了射线,并且没有限制射线投射可以检测到的碰撞体。对碰撞体的限制往往用作过滤器,而不是识别单个碰撞体。需要的是有关射线投射 (Raycast) 准确击中的对象的信息,以便可以检查这是否是玩家角色。 但有一个问题:从方法中获取信息的方式是通过其返回值,而这里的 Raycast 仅返回布尔值。但幸运的是有非常相似的 Raycast 方法,这个方法使用?out 参数。 out 参数的工作方式与普通参数相同,不同之处是参数前面要写关键字“out”。这些参数的值可以由它们的方法更改或设置,以便能够由任何调用方使用。out 参数有一个名为?RaycastHit?的类型,并且 Raycast 方法会将其数据设置为有关射线投射命中的任何对象的信息。 在创建 Ray 的代码行与 Raycast if 语句之间,添加以下代码:
该行代码定义了 RaycastHit 变量。 接下来,需要更改 Raycast 方法以便使用此变量。将包含 Raycast 方法的 if 语句更改为如下所示:
这是一个不同的 Raycast 方法,其工作方式非常类似,但使用 out 参数返回信息。 现在,脚本可以识别玩家的角色是否在范围内、执行射线投射并知道是否有任何对象被击中。接下来,需要检查击中了什么。 在 Raycast 的 if 语句中,添加以下代码:
25. 为了给 Nav Mesh Agent 编写任何脚本,需要包含其命名空间。 在脚本顶部与其他 using 指令一起,添加以下代码:
包含 AI 命名空间将让您能够访问?NavMeshAgent 类。
这个对组件的公共引用将使您能够在 Inspector 窗口中分配 Nav Mesh Agent 引用。 需要设置幽灵应该巡逻的路径点。Nav Mesh Agent 的目标是 Vector3 矢量,即世界空间中的位置。但是,假如将路径点设置为 Vector3,则必须手动设置所有位置,并希望使用的数字准确无误。 相反,合理的做法是采用一组空游戏对象并将它们的位置用作路径点。但是,可以不引用一组游戏对象,而只是引用这些游戏对象的 Transform 组件。可以直接声明几个公共 Transform 变量,然后在 Inspector 窗口中分别设置每个变量,但在每个幽灵可以拥有的路径点数量方面,这种方案没有太大的灵活性。 实际上,更好的方案是使用数组。数组是一起存在的变量的基本集合。数组是通过方括号定义的。 在 navMeshAgent 变量声明下面添加以下行
让我们继续向脚本添加: .当幽灵到达设置为目标的最后一个路径点时,需要继续前进到下一个路径点。跟踪下一个路径点的最简单方法是存储路径点数组的当前索引。 在 waypoints 数组声明下面,添加以下代码:
.接下来,让我们前往 Update 方法,以便可以使用这个索引。 在 Update 方法中,需要执行检查:您想知道 Nav Mesh Agent 是否已到达其目标。一种简单的检查方法是查看到目标的剩余距离是否小于先前在 Inspector 窗口中设置的停止距离。 在 Update 方法中添加以下 if 语句:
.现在,需要更新当前索引,然后将其用于设置 Nav Mesh Agent 的目标。为此,将使用一个称为求余运算符的新运算符,该运算符由百分比字符?%?表示。 在 if 语句中添加以下代码:
代码表示:“将当前索引加 1,但是如果该增量导致索引等于 waypoints 数组中元素的数量,则将索引设置为零。”在这种情况下,索引将被设置为零,因为任何数字除以本身时,余数均为零。 现在已经增加了索引(并在必要时将其循环回零),接下来需要使用索引。在索引增量设置下面添加以下代码:
这与?Start 方法中所做的完全一样,唯一不同之处是使用幽灵当前所在的路径点作为索引,而不是使用零作为索引。 26.
向 if 语句中添加对 Play 方法的调用:
27. if?(Input.GetKeyDown(KeyCode.R)) { GetComponent<Renderer> ().material.color = Color.red; 28.全屏地图 public static FullscreenMap Instance { get; private set; } 29. 迷你地图 public class MinimapSystem public class MinimapElement : MonoBehaviour public class MinimapUI : MonoBehaviour |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/11 20:49:25- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |