1、标签(Tag)和图层(Layer)
他们都用于游戏物体分类,但是侧重点不一样。
标签便于代码中对特定物体进行操作。
图层则服务于渲染和碰撞管理,如控制摄像机渲染、光源影响及碰撞设置。
标签和图层的位置:
(1)标签Tag
用来对游戏物体进行分类的,从而更加方便的在代码中对某一类物体进行统一操作。
常用函数:
函数名 | 功能 |
GameObject.FindWithTag() GameObject.FindGameObjectWithTag() | 查找场景中指定标签的物体,但是当场景中有多个同样标签的物体时,无法保证返回的时哪一个。 |
GameObject.FindGameObjectsWithTag() | 返回场景中指定标签的所有物体 |
(2)层Layer
为了渲染和碰撞进行分类。
1)让摄像机只渲染某些层的物体,对另一些层的物体不渲染(即不显示)
2)让光源只照亮某些层的物体,而对另一些层的物体不影响。
3)供射线投射用于选择性地忽略碰撞体或创建碰撞
函数名 | 功能 |
Physics.Raycast() | 发射射线、检测碰撞。其中有一个参数可以选择射线可以与哪些层的物体发生碰撞检测 |
collider2D.IsTouchingLayers() | collider是一个2D碰撞体,此函数判断此2D碰撞体是否与指定层上的物体接触 |
gameObject.layer | 获取该游戏物体对应的层 |
4)设置层与层之间能否碰撞
在【Edit -> Project Settings -> Physics】中,
用来设置层与层之间能否发生碰撞的。如果把✔去掉,就表示行和列分别对应的两个层不会发生碰撞。
2、预制体
(1)预制体变体
当你将一个已经是预制体的游戏对象再次拖入Assets窗口时,弹窗就会提示,想要创建另一个原始预制体还是想要创建该原始预制体的变体。当选择第二个选项,则预制体变体创建成功。
预制体变体是原始预制体的派生类(是子类),子类也受到基类的影响,但也可以和基类有不同的地方。其不同的地方不受基类影响,子类也可以New实例,叫做预制体变体实例。
(2)修改预制体
如果Hierarchy中预制体实例被修改了,面板上就会多出一些选项。
当前预制体实例添加了2物体之后,图片出现"+"号,这表示这个2是新添加的,并不是原始预制体本身拥有的。此时可以:
1)Revert All:重置预制体,清除所有修改,把预制体变回原来的样子
2)Apply All:应用所有修改,报错所有修改,此时Assets中的预制体也将被改变
(3)将预制体实例变回一个普通的GameObject
断绝预制体实例和Assets中预制体的关系,它就会变回一个普通的游戏物体。
(4)删除预制体
当删除了Assets中的预制体,Hierarchy中的此预制体实例会变红,这时在提示我们预制体丢失,但不会影响使用,想让他不再是红色,破坏它把它变回普通游戏物体即可。
3、Time类使用
属性 | 功能 |
Time.time | 游戏开始到现在所花的时间,单位是秒。 |
Time.timeScale | 时间缩放值,值1意味着实时。值0.5意味着半速,值0意味着暂停。用于游戏的快进暂停功能 |
Time.deltaTime | 上一帧到这一帧的游戏时间 |
Time.fixedDeltaTime | 固定时间间隔 |
4、异步加载场景
示例代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class AsyncTest : MonoBehaviour
{
private AsyncOperation operation;
float timer = 0;
// Start is called before the first frame update
void Start()
{
StartCoroutine(loadScene());
}
IEnumerator loadScene()
{
operation = SceneManager.LoadSceneAsync("SampleScene");
operation.allowSceneActivation = false;
yield return operation;
}
// Update is called once per frame
void Update()
{
Debug.Log(operation.progress);
timer += Time.deltaTime;
if(timer > 5)
{
operation.allowSceneActivation = true;
}
}
}
5、角色移动
(1)直接修改组件位置
最基础的方式,是改变物体位置的最直接的方式。
适用于既没有物理系统,也对移动没有特殊要求的情况。
示例:
public class MoveTest : MonoBehaviour
{
public float speed;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Move();
}
void Move()
{
float moveX = Input.GetAxisRaw("Horizontal");
float moveZ = Input.GetAxisRaw("Vertical");
Vector3 dir = new Vector3(moveX, 0, moveZ).normalized;
transform.Translate(dir * Time.deltaTime * speed);
}
}
注意!!
1)GetAxis和GetAxisRaw的区别:如果你希望有一个平滑的输入响应,适用于移动角色等需要渐变效果的情况,可以使用 Input.GetAxis("Horizontal")。如果你需要快速、立即响应的输入,比如在一些快节奏的游戏中,可能更适合使用 Input.GetAxisRaw("Horizontal")。
2)直接移动的方法汇总:
- transform.Translate(dir * Time.deltaTime * speed);
- transform.position += dir * Time.deltaTime * speed;
- transform.TransformPoint(dir * Time.deltaTime * speed);
(2)资源商城下载角色控制系统成品
比如去商城搜索 3rd person
(3)角色控制器组件Character Controller
向人物添加Character Controller组件
参数 | 描述 |
Slope Limit 斜度限制 | 可直接沿着向上移动的最大坡度 |
Step Offset 每步偏移量 | 可直接跨越的最大障碍高度 |
Skin Width 蒙皮厚度 | 皮肤厚度,值较大可减少抖动,较小可能导致角色卡住,一般设置为半径的10%(ps:但是这样会导致角色挨不着地面,所以这时候可以调整Center的Y轴值,即可使角色接触地面) |
Min Move Distance 最小移动距离 | 当橘色的单次移动距离小于该值时,则被忽略,不生效。可用于减少抖动 |
Radius & Height 半径和高度 | 所控制角色的半径和高度 |
示例:
public class MoveTest : MonoBehaviour
{
private CharacterController player;
// Start is called before the first frame update
void Start()
{
player = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(horizontal, 0, vertical);
player.SimpleMove(dir);
if(player.isGrounded)
{
Debug.Log("正在地面上...");
}
}
}
注意!!移动的两个方法Move和SimpleMove的区别:
1)Move为更复杂的移动,不计算重力影响。
- 无重力效果,自定实现重力,可做跳跃功能
- 返回值(CollisionFlags对象),返回角色与物体碰撞的信息
2)SimpleMove:以一定速度来移动,移动时自动计算重力因素影响
- 不受Y轴速度影响,自带重力吓偶句,无法实现跳跃功能
- 返回值为Bool,当角色接触地面返回True,反之为False
- SimpleMove方法是CharacterController组件提供的一个用于处理角色平面移动的简化方法,它自动处理了角色与地面的碰撞检测和摩擦,但它不支持跳跃等垂直方向的动作
(4)通过物理系统自己做
通过物理方式对物体施加力,改变物体运动状态的方式让物体移动,其中最核心的组件就是Rigidbody。
Rigidbody参数说明:
示例:
public class MoveTest : MonoBehaviour
{
Rigidbody rb;
public float speed;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(horizontal, 0, vertical).normalized;
rb.MovePosition(transform.position + dir * Time.deltaTime * speed);
}
}
刚体移动的方法:
- AddForce: rb.AddForce(dir * speed * Time.deltaTime)
- 修改velocity:rb.velocity += dir * speed * Time.deltaTime
- MovePosition: rb.MovePosition(transform.position + dir * speed * Time.deltaTime);
(5)CharacterController和Rigidbody的区别
1)CharacterController
- 处理斜坡
- 处理台阶
- 不会卡墙
2)Rigidbody
- 自带重力
- 提供阻力
- 可以和物理对象交互
(6)完整的角色控制器代码
示例代码:
public class MoveTest : MonoBehaviour
{
private CharacterController cc;
public float speed = 12f;
public float gravity = -9.81f;
public float jumpHeight = 3f; // 跳跃高度
public Transform groundCheck; // 用来获取生成球体的位置
public float groundDistance = 0.4f;
public LayerMask groundMask; // 值判断为地面的层
Vector3 velocity;
bool isGrounded; // 检测是否在地面
// Start is called before the first frame update
void Start()
{
cc = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
// CheckSphere 检验球,创建一个看不见的球用来检测,碰到就是true没有碰到就是false
// 第一个值是球的位置,第二个是圆的半径,第三个是可筛选的层
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask); // 检测是否在地面
if ((isGrounded && velocity.y < 0))
{
velocity.y = -2;
}
float moveX = Input.GetAxisRaw("Horizontal");
float moveZ = Input.GetAxisRaw("Vertical");
Vector3 dir = (transform.right * moveX + transform.forward * moveZ).normalized;
// 平移
cc.Move(dir * speed * Time.deltaTime);
if(Input.GetButtonDown("Jump") && isGrounded)
{
// 物理公式 v=sqrt(v*-2*g)
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
// 再乘一个Time.deltaTime是由物理决定的1/2gt^2
cc.Move(velocity * Time.deltaTime);
}
}
6、拖尾(Trail Render组件)
新建拖尾(右键 -> 效果 -> 拖尾新增),也可以在其他物体上加Trail Render组件。
实现简单的拖尾修改配置如下:
效果:
7、游戏对象的Transform
Transform属性可以进行位置、旋转、大小的设置。
1)位置:position
2)旋转:rotate
3)大小:localScale
左右翻转怎么做?
position不行,rotate不行,所以可以考虑localScale属性。
localScale对应坐标的值*-1即可。
x值从1变为-1后: