Unity初级常用API
碰撞检测
对于一个触发器,碰撞事件的三个状态:
- OnTriggerEnter2D: 开始碰撞
- OnTriggerStay2D: 碰撞中
- OnTriggerExit2D: 碰撞分开
void OnTriggerEnter2D(Collider2D collider)
{
Debug.Log("撞到啦...");
Debug.Log(collider.gameObject.tag);
}
// 碰撞检测函数,进入的时候执行
void OnTriggerStay2D(Collider2D collider)
{
Debug.Log("一直停留在碰撞状态…");
}
// 停留的时候执行
void OnTriggerExit2D(Collider2D collider)
{
Debug.Log("退出碰撞状态…");
}
// 退出的时候执行
使用条件:检测的对象必须拥有col相关组件碰撞脚本,而且这个适用于触发器
如果检测器不是触发器,即需要有具体的物理系统,则使用如下对应函数:
private void OnCollisionEnter(Collision collision)
{
print(collision.gameObject.name);
}
private void OnCollisionExit(Collision collision)
{
print(collision.gameObject.name);
}
非物理碰撞检测(Bounds 外包围盒)
有时候由于脚本冲突,比如对象不是按照官方的物理逻辑在编写碰撞的,则直接检测是否经过而不是判断物理碰撞来检测碰撞
使用Bounds
API
bounds.center
bounds.size
bounds.min
bounds.max
bounds.center.x
bounds.center.y
其中center和size只读
常用方法:
public bool Contain(Vector3 point);//判断点是否在内部
public void Encapsulate(Vector3 point);//自动扩充大小来包括这个点
public void Encapsulate(Bounds bounds);//自动扩充大小来把这个bounds包括
public bool IntersectRay(Ray ray);//判断这个射线是否与包围盒相交
public Vector3 ClosestPoint(Vector3 point);//包括盒最近的点
public void SetMinMax(Vector3 min,Vecor3 max);//设置边界框的最小最大值
与Collider的区别:Bounds不会跟着模型旋转,只会跟着变大变小,作为五向的,精度更小
包围盒的类型
- AABB包围盒(Axis-aligned bounding box)
- 包围球(Sphere)
- OBB包围盒(Oriented bounding box)
- 凸包包围盒(Convex Hull)
AABB:构造简单,存储空间小,紧密性差,对于不规则体荣誉空间大,两个点描述(立方体对角线)
从算法角度上看,其实就是计算两点在坐标轴上的投影,然后对比两个对象的投影在坐标轴上的描述,如果xyz轴(如果是2D则xy轴)都有交叉段,则判断相撞
与OBB差别:不可旋转
判断某点是否在Bounds内
Vector3 pos = someRenderer.transform.position;
Bounds bounds = myBoxCollider.bounds;
bool rendererIsInsideTheBox = bounds.Contains(pos);
带碰撞的
Bounds rendererBounds = someRenderer.bounds;
Bounds colliderBounds = myBoxCollider.bounds;
bool rendererIsInsideBox = colliderBounds.Intersects(rendererBounds);
get与set属性访问器(其实是刚好了解到这个东西才写进来的)
一般情况下在C#中编写脚本声明变量时:
private float num;
public int index;
其实隐藏了get与set:
public float Num
{
get { return Num; }
set { Num= value; }
}
get
与set
内的定义其实就是上述,get返回Num的值,调用Num时返回Num本身,也就拿到了Num值,set让Num附上value值,所以说这两个相当于“读”和“写”,其具体作用其实也是在声明读和写
一般声明变量,unity默认为读写,也就是默认这两个访问器都能用,但如果自行编写这两个访问器的其中之一,那么就相当于编写成“只读”或“只写”
private float num//只读属性,只能读取该属性的值
{
get { return num; }
}
private float num//只写属性,只能给该属性设置值
{
set { num = value; }
}
private float num//可读可写的属性
{
get { return num; }
set { num = value; }
}
在C++中,我们为变量赋值时,可能会遇到变量有一定范围的需求,于是我们一般创建一个新变量来做判断以限定范围:
int a;//假如a范围为0~10
int b;
cin<<b<<endl;
if(b>=0&&b<=10)
{
a=b;
}
这样的目的是保持变量安全性,a永远不可能被外界设置成0到10以外的值
这个方式和C#中使用get与set保护变量有异曲同工之妙:
private float num;
public float Num
{
get { return num; }
set //value小于等于10
{
if (value>10)
{
value = 10;
}
num = value;
}
}
建立新值num来为Num赋值,看似多此一举,其实就是防止Num溢出
不过最标准的命名变量的方式可能是如此:
private float num{get;set;};
用来强调可读可写