unity游戏(M)记录基础设置以及layer

本文介绍了如何在Unity2022.1.24版本中进行账号绑定、项目设置,包括2D模板、通用渲染管线的使用,以及VS连接、素材获取、像素风格调整、瓦片地图和叠层的概念,为初学者提供了一个详细的入门指南。

一些记录

Unity

账号绑定微信,同时绑定qq邮箱,下载版本2022.1.24

创建项目使用该版本编辑器,2d(urp)模板,通用渲染管线,具有好的画面效果和2d灯光
在这里插入图片描述

初学时候项目创建不需要点右下角,防止网络不通畅带来的问题

确定unity与vs连接好?
在这里插入图片描述

使用unityhub安装代码编辑器可以自动配置好vs

在界面下方创建c#文件后双击进入打开vs后发现代码能亮的都亮了(显示unity引用注释),说明链接成功。
存在无法链接的问题,退出vs后再在如下界面右击点击打开c#文件,vs会重编译连接。
在这里插入图片描述

//此外,需要在如下界面确认是否有vs editor,表示可以将vs与unity链接起来,可以在vs编辑器中有代码提示和debug(当然这不是此外,只是有一次看了一下编辑器连在一起了吗)

素材获取
网站:

itch素材查找https://itch.io/
素材直接拖入assets中
在这里插入图片描述

此外,需要做的调整设置(将每一个创建的物体都放在000坐标处)、
在这里插入图片描述

像素风格及图片设置

1.这里的素材中像素图片每一个黑白或灰色的格子都代表16*16的像素格子
在pixels per unit的数量表示一个格子里的像素数量有多少,也就是说每一个黑白或灰色的格子中可以显示多少个像素单位
在这里插入图片描述

如图素材是16*16的
也就是说可以将pixels per unit修改成16
在这里插入图片描述

2.像素游戏通常不需要对游戏图片放大缩小时候用相邻像素点的颜色填充,故可以将过滤模式改为point无过滤
在这里插入图片描述

3.将压缩改为无压缩,保证图片的最佳像素比例
在这里插入图片描述

4.点击apply这样可以产生满足像素风格的锯齿

图集的查看和分割

一,人物素材分割
1.如图完成设置,还原像素图片的锯齿状清晰度
在这里插入图片描述

2.多图片分割,相比起自动分割模式(会将每一个小图片分割成不同长和宽的图片,导致无法准确找到锚点等),选择图片等分8*11,此外将锚点pivot设置在底部中心
在这里插入图片描述

3.点击右上角的apply,完成切割设置
4.此外还需要在inspector窗口点击apply(好像不需要,这个窗口没有*)
5.展开分割好的图片,选中一个通过拖拽到hierarchy中完成布置

二,环境素材分割

以1616为一个unit分割场景单元
在这里插入图片描述

2d场景的绘制

1.打开瓦片调色盘完成2d场景绘制
在这里插入图片描述
创建位置需要与场景设置在同一层,方便管理(添加瓦片地图,以及下边的调色盘文件夹)

在这里插入图片描述
2.将分割好的场景拖拽到瓦片调色盘菜单栏中间大空白处。
此时需要确定这个调色盘的位置,如图,tilemap下边放置一个瓦片们,这个瓦片叫做forest 1
在这里插入图片描述

3.在hierarchy下边创建网格,创建2d物体,方形的tilemap。此时将瓦片调色盘中就有可以使用的瓦片地图了(active tilemap),由于分割时没有注意到每一个方格的锚点(放在了底部),锚点对准每一个块的底部中心,需要更改成center

在这里插入图片描述

ps.调整画面的尺寸

可以切换做3d模式通过按住鼠标右键点击wasd来控制移动三弟位置
在这里插入图片描述

可以看到图片2d平面的图片 是由摄像机在一个位置投影出来的,通过在heirarchy中的maincamera的数值size的更改可以调整画面的尺寸

在这里插入图片描述

叠层的概念

绘制出上草皮之后发现人物被挡在了草皮之后
在这里插入图片描述
欲通过叠层将草皮放在叠层之后

1.renderer渲染,渲染的图片是哪一张就会显示哪一张
在这里插入图片描述
2.叠层的概念

在这里插入图片描述
通过更改同一层的order来改变层序,将场景草图层放在-1层

为了避免在同一层需要添加无数个order,可以直接添加图层

在这里插入图片描述

这样,在unity中下方的图层(新添加的图层)永远在上方的前面,所以只需要更改图层就可以改变顺序

要对场景前后层次做划分,将对应的瓦片放置在对应的图层,同意图层下改变order

在这里插入图片描述

在对应的图层绘制场景

在这里插入图片描述

<think>我们想要在Unity中创建一个区域,当物体进入该区域时,持续受到一个自定义的重力作用。Unity的全局重力(Physics.gravity)是作用于所有启用了重力的刚体的,无法为特定区域设置不同的重力。因此,我们需要通过其他方法来实现。 思路: 1. 创建一个区域(例如使用一个带有Collider的GameObject,并设置为触发器)。 2. 当带有Rigidbody的物体进入该区域时,我们给该物体施加一个持续的自定义力来模拟重力。 3. 当物体离开该区域时,停止施加这个力(或者恢复原来的重力设置)。 但是注意:全局重力可能一直存在,所以我们需要在物体处于自定义重力区域时,暂时禁用物体受到的全局重力,并在离开时恢复。或者我们可以在整个过程中忽略全局重力,而完全用自定义力来代替。 具体步骤: a) 创建一个空物体,添加一个Collider(如Box Collider或Sphere Collider),并设置为触发器(Is Trigger = true)。 b) 编写一个脚本,附加到该区域上,用于检测进入和离开的物体,并对这些物体的刚体施加自定义的力。 c) 在脚本中,我们可以定义一个自定义的重力方向和大小(例如Vector3类型的字段)。 d) 当物体进入时,我们可以禁用该物体刚体的useGravity(这样它就不会受到全局重力的影响),然后每帧(或在FixedUpdate中)给物体施加一个自定义的力(使用ForceMode.Acceleration,这样会忽略质量,直接产生加速度)。 e) 当物体离开时,重新启用useGravity,并停止施加自定义力。 但是注意:如果物体同时处于多个重力区域,我们需要更复杂的管理(比如使用栈来记录)。这里我们只考虑简单情况。 另一种方法是:不改变useGravity,而是通过计算抵消全局重力,并施加自定义重力。这样,当物体离开区域时,自动恢复全局重力。但这样需要计算两个力的叠加。 这里我们采用第一种方法:禁用全局重力,施加自定义重力。 代码实现(假设区域是2D,使用Rigidbody2D;如果是3D,将Rigidbody2D替换为Rigidbody,ForceMode2D.Force改为ForceMode.Acceleration): 注意:在2D中,我们使用Rigidbody2D,并且没有ForceMode2D.Acceleration,所以我们可以用ForceMode2D.Force并乘以质量来模拟加速度(因为F=ma)。 但是,在3D中,我们可以直接使用ForceMode.Acceleration,它会忽略质量,直接按加速度施加。在2D中,我们需要自己计算力:force = mass * customGravity。 这里我们以3D为例,因为3D有ForceMode.Acceleration,使用起来更直接。 步骤: 1. 创建区域(GameObject + Collider(设置为trigger))。 2. 创建脚本CustomGravityArea.cs,并附加到该区域。 代码示例(3D): ```csharp using UnityEngine; using System.Collections.Generic; public class CustomGravityArea : MonoBehaviour { public Vector3 customGravity = new Vector3(0, -10f, 0); // 自定义重力,例如向下10m/s² // 存储进入区域的刚体及其原始useGravity状态 private Dictionary<Rigidbody, bool> originalGravitySettings = new Dictionary<Rigidbody, bool>(); private void OnTriggerEnter(Collider other) { Rigidbody rb = other.GetComponent<Rigidbody>(); if (rb != null) { // 记录原来的useGravity设置,并禁用全局重力 originalGravitySettings[rb] = rb.useGravity; rb.useGravity = false; } } private void FixedUpdate() { // 对区域内的每个刚体施加自定义重力 foreach (var rb in originalGravitySettings.Keys) { if (rb != null) // 防止物体被销毁后出现空引用 { // 施加力,忽略质量(因为使用ForceMode.Acceleration) rb.AddForce(customGravity, ForceMode.Acceleration); } } } private void OnTriggerExit(Collider other) { Rigidbody rb = other.GetComponent<Rigidbody>(); if (rb != null && originalGravitySettings.ContainsKey(rb)) { // 恢复原来的useGravity设置 rb.useGravity = originalGravitySettings[rb]; originalGravitySettings.Remove(rb); } } // 当物体被禁用或销毁时,清理字典 private void OnDisable() { // 离开时恢复所有物体的重力设置 foreach (var kvp in originalGravitySettings) { if (kvp.Key != null) { kvp.Key.useGravity = kvp.Value; } } originalGravitySettings.Clear(); } } ``` 注意: - 使用FixedUpdate施加力,因为物理计算在FixedUpdate中进行。 - 使用字典记录每个进入区域的刚体原来的useGravity设置,以便离开时恢复。 - 当区域被禁用或销毁时,需要恢复所有物体的重力设置(在OnDisable中处理)。 - 如果物体在区域内被销毁,我们不需要处理,因为当物体销毁时,其刚体也会被销毁,在FixedUpdate中会跳过(通过rb!=null判断),但在OnDisable中我们同样做了非空检查。 对于2D的情况,需要稍作修改: 1. 使用Collider2D和Rigidbody2D。 2. 因为Rigidbody2D没有ForceMode.Acceleration,我们需要自己计算力:force = customGravity * rb.mass。 3. 施加力时使用ForceMode2D.Force。 2D版本代码修改点: - 将Collider改为Collider2D,Rigidbody改为Rigidbody2D。 - 在FixedUpdate中施加力:rb.AddForce(customGravity * rb.mass); - 注意:customGravity在2D中可以是Vector2类型。 另外,引用[1]中提到,在Unity中可以通过设置刚体的Gravity Scale(重力缩放)来调整全局重力对单个刚体的影响。但这种方法只能统一缩放全局重力,不能改变方向,也不能在特定区域内实现。因此,我们这里没有使用Gravity Scale,而是直接覆盖了重力。 引用[2]和[3]提到了使用Impulse模式施加力,但那是瞬时的力。我们这里需要持续施加的力,所以使用持续力(每帧施加)更合适。 总结: 通过以上方法,我们可以在Unity中创建一个区域,持续施加自定义重力。当物体进入区域时,禁用全局重力并持续施加自定义重力加速度;离开时恢复全局重力设置。 注意事项: - 如果物体同时进入多个自定义重力区域,需要更复杂的逻辑(例如使用栈来记录每个区域的重力设置,或者只让最内层的区域生效)。这里我们只处理单个区域的情况,多个区域同时影响需要额外处理。 - 自定义重力的方向可以是任意的,不一定要向下。 扩展:如果希望区域内的重力方向指向某个中心(比如星球引力),则需要计算物体到中心的向量,然后归一化后乘以重力大小,然后施加。这种实现类似行星引力场。 §§相关问题§§ 1. 如何实现一个球形重力区域(类似星球引力)? 2. 多个重力区域重叠时,如何管理物体的重力? 3. 如何用Shader可视化重力区域? 4. Unity中如何模拟零重力环境?</think>### Unity设置区域持续施加重力的实现方法 在Unity中创建持续施加自定义重力的区域,可以通过**触发器检测+物理力施加**的组合实现。以下是完整解决方案: #### 核心实现步骤 1. **创建重力区域** ```csharp public class GravityZone : MonoBehaviour { public Vector3 customGravity = new Vector3(0, -15f, 0); // 自定义重力值 public float gravityScale = 1.5f; // 重力缩放系数[^1] private void OnTriggerStay(Collider other) { Rigidbody rb = other.GetComponent<Rigidbody>(); if (rb != null) { // 方法1:直接施加加速度力(忽略质量) rb.AddForce(customGravity, ForceMode.Acceleration); // 方法2:通过重力缩放系数修改[^1] // rb.AddForce(Physics.gravity * gravityScale, ForceMode.Acceleration); } } } ``` 2. **配置场景对象** - 创建空GameObject,添加碰撞体(如Box Collider) - 设置碰撞体为**触发器**(Is Trigger = true) - 附加上面的脚本并调整参数: ```csharp customGravity = new Vector3(0, -25f, 0); // 2.5倍重力 ``` #### 进阶实现技巧 1. **行星引力效果**(指向中心的重力): ```csharp private void OnTriggerStay(Collider other) { Rigidbody rb = other.GetComponent<Rigidbody>(); if (rb != null) { Vector3 direction = (transform.position - other.transform.position).normalized; rb.AddForce(direction * gravityStrength, ForceMode.Acceleration); } } ``` 2. **多层重力区域管理**: ```csharp private Dictionary<Rigidbody, int> activeGravityZones = new Dictionary<Rigidbody, int>(); void OnTriggerEnter(Collider other) { Rigidbody rb = other.GetComponent<Rigidbody>(); if (rb != null) { if (activeGravityZones.ContainsKey(rb)) activeGravityZones[rb]++; else activeGravityZones.Add(rb, 1); } } void FixedUpdate() { foreach (var rb in activeGravityZones.Keys.ToList()) { if (rb != null) rb.AddForce(customGravity * activeGravityZones[rb], ForceMode.Acceleration); } } ``` #### 关键注意事项 1. **物理更新时机**:力施加代码必须放在`FixedUpdate()`或`OnTriggerStay()`中,确保与物理引擎同步[^2] 2. **性能优化**: - 对静态物体禁用重力计算 - 使用`LayerMask`过滤受影响的物体 ```csharp public LayerMask affectedLayers; void OnTriggerStay(Collider other) { if (((1 << other.gameObject.layer) & affectedLayers) != 0) { // 施加重力 } } ``` 3. **可视化调试**:在`OnDrawGizmos()`中添加区域可视化 ```csharp void OnDrawGizmos() { Gizmos.color = new Color(1, 0, 0, 0.3f); Gizmos.DrawCube(transform.position, GetComponent<BoxCollider>().size); } ``` #### 不同场景的解决方案 | 需求类型 | 实现方案 | 适用场景 | |----------|----------|----------| | **均匀重力场** | `AddForce(constantVector)` | 传统重力区域 | | **行星引力** | 指向中心的标准化向量 | 星球模拟 | | **方向切换区** | 根据接触面计算方向 | 平台解谜游戏 | | **抗重力区** | 设置`customGravity = Vector3.up * 9.81f` | 反重力区域 | > **提示**:对于2D项目,需将`Rigidbody`替换为`Rigidbody2D`,`Collider`替换为`Collider2D`,并使用`Physics2D.gravity`[^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值