持续更新中,最近更新:2023-2-7
1.获取其他类的公共变量
比如我在GameObject A上挂载了脚本scriptA,编写scriptB时想要调用scriptA中的变量(此处举例为 public int num)。
那么我在B中可以先定义一个public GameObject objA;
然后在方法中通过 int dataA =objA.getComponent<scriptA>().num;就可以获取到num的值。
2.检测输入的逻辑值
public static float GetAxis(string axisName);
例如:
float moveX=Input.GetAxisRaw(“Horizontal”);//水平方向A:-1,D:1,无输入为0
axisName可在引擎的Edit-Project Settings-Input Manager中查看
3.Vscode 编译时没有出现unity相关提示
(1).Net Framework版本不对
编辑-项目设置-Player-Api兼容级别查看
vscode中csproj文件中查看
framework部署地址
选择开发人员工具包,下面的中文(简体)那些都是拓展语言包,没有开发人员工具包无法发挥作用
vscode也会在这里提示你(此为正常运行),如果缺失会显示Attempted to update project that is not loaded,也就是说加载framework失败,不会出现unity的相关代码补全
4.游戏内暂停的实现
网上一般是选择timescale设置为0,但是update内的方法依然会做出响应。比如角色移动时贴图状态会发生变化,仅是timescale=0的话,输入移动键虽然不会使玩家位移,但仍会使其贴图进行相应变化。这里谈谈我自己的思路。
timescale=0,同时断开玩家的输入。玩家影响游戏的方式均是通过输入,因此断开输入就保证了游戏不再受外界影响,timescale=0也使游戏自身的时间停止流动,实现了所谓的暂停。
那么我们就可以将所有的键盘输入事件放在一个类中,通过具体场景实现按键的不同功能,以此能进行更多拓展,比如我打开一个菜单,那么这时就可以断开地图场景的键盘事件,连接菜单场景的键盘事件,就像wasd选择选项而不再是移动
实现的方式有很多,我举个例子
public int mode = 0;//根据场景切换 void Update() { switch(mode) { case 1://键盘按下的键 { if (Input.GetKeyDown(KeyCode.W)) Debug.Log("W"); if (Input.GetKeyDown(KeyCode.A)) Debug.Log("A"); if (Input.GetKeyDown(KeyCode.S)) Debug.Log("S"); if (Input.GetKeyDown(KeyCode.D)) Debug.Log("D"); break; } case 2://二维平面场景的方向 { if (Input.GetKeyDown(KeyCode.W)) Debug.Log("+y"); if (Input.GetKeyDown(KeyCode.A)) Debug.Log("-x"); if (Input.GetKeyDown(KeyCode.S)) Debug.Log("-y"); if (Input.GetKeyDown(KeyCode.D)) Debug.Log("+x"); break; } } }
如果所有键盘事件均在此类中,则case=0相当于断开玩家的键盘输入途径
5.按钮的键盘选中
在菜单中通过wasd或上下左右(受项目设置的输入管理器影响)选择按钮(或是其他可选目标)
unity按钮自带导航
可视化之后能在场景中看到其关系
导航通过水平和垂直方向进行选择,explicit则是自定义上下左右的目标
一般得先进入选中状态才能通过键盘进行切换,这时我们可以给想要默认选中的游戏对象添上这句代码
你还可以通过给button挂上event trigger组件来添加选中事件
5.获取物体尺寸
6.Debug.Log和print的区别
print继承monobehaviour,因此在没有继承该类的脚本中无法执行,而Debug.Log没有该限制。此外没什么区别。
7.U3D 摄像机范围限制
方案1
private void LateUpdate()
{
transform.position = new Vector3(Mathf.Clamp(transform.position.x, -10f, 7.5f), y.data,z.data);
}
transform.position摄像机位置,Mathf.Clamp(data,min,max),参数依次为数据,最小值,最大值。
将该语句写入LateUpdate()中,因为摄像机的移动一般位于update,因此在lateupdate中能通过该语句对摄像机范围进行修正和限制
8.凹面碰撞体的判定
两个物体的碰撞的要求是都具有碰撞盒,但只需要一方有刚体就可以触发碰撞
凹面模型如果不挂载刚体,则不勾选convex时,网格碰撞盒(mesh collider)会非常精确,物理模拟更佳
(适用于静止不动的,如地图等对象)
如果凹面模型需要挂载刚体,则需要勾选convex,此时所有凹部分会被填平,网格碰撞盒会不够精确,如果要进行精确的物理模拟,需要使用其他碰撞盒组合出需要的碰撞网格
(适用于需要进行操控或移动的对象)
9.对于委托和事件的理解
委托相当于一个母函数入口,母函数中可以添加多个子函数(委托的儿子代),而该子函数可以为一个事件,事件之下又可以添加子函数(儿子的孙子代)。当执行委托或事件时,会依次执行其下挂载的子函数。
- 委托定义了方法的类型:是否传参,是否返回数据
- 事件基于委托
- 挂载方法时使用加法运算符
- 委托和事件上挂载的方法的类型都必须与委托相同
- 委托可以在任意处声明,事件只能在类中声明
以下是委托的例子
using System.Collections.Generic;
using UnityEngine;
public delegate void PetName(string name); //委托 (需要一个string类型的参数当宠物名称)
//陆地动物类
public class TestA : MonoBehaviour
{
PetName petName; //声明委托
void Start()
{
//委托
petName += Dog; //狗
petName += Cat; //猫
//调用委托事件
petName("大白");
}
//狗 因为委托调用所以需要一个string参数
void Dog(string name)
{
Debug.Log($"我叫{name},是一只猫");
}
//猫
void Cat(string name)
{
Debug.Log($"我叫{name},是一只狗");
}
}
这里的结构就是
可以看到,子函数结构与委托结构一致,子函数传入参数与委托传入参数相同。
以下是事件的例子
using System.Collections.Generic;
using UnityEngine;
//鸟类
public class TestB : MonoBehaviour
{
public static event PetName SayHelloEvent;//事件
void Start()
{
//在事件中添加方法
SayHelloEvent = Parrot;
SayHelloEvent += Pigeon;
SayHelloEvent("小白");
}
//鹦鹉
public static void Parrot(string name)
{
Debug.Log($"我叫{name},是一只鹦鹉");
}
//鸽子
public static void Pigeon(string name)
{
Debug.Log($"我叫{name},是一只鸽子");
}
}
结构为
可以看到,这里并没有声明新的委托,而是在TestB类中声明了基于PetName委托的事件,然后在Start中执行了该事件。该事件也仅存于TestB中。
总之,委托和事件在处理多函数的业务中比较方便,在后续更改中只需要在负责业务的委托或事件中添加子函数就可以达成目的。