灯光
基本项
烘焙
灯光的种类
Lighting窗口
预设体
了解预设体
利用代码操作预设体
实例化预设体Instantiate
//预设体的类型也是GameObject,名字是CubePre。
public GameObject CubePre;
//注意这一步:在unity中,将预设体关联到脚本的变量上来。
void Start () {
/*法一:实例化到指定位置。
预设体,位置(中心),旋转(默认四元数。此处设为不转)。返回值是刚生成的物体。*/
GameObject go = Instantiate(CubePre, transform.position, Quaternion.identity);
//法二:不指定位置的实例化。
Instantiate(CubePre);
}
删除
位置:Start
删除物体
/*删除物体。一般是在一帧完了之后删除。
不能写在Update里,因为这个删除是有延迟的,和垃圾回收机制一样。*/
Destroy(go);
3秒之后删除
Destroy(go, 3f); //3秒之后删除
立刻删除
//立刻删除(强制删除)。可以写在Update里。费性能,少用。
DestroyImmediate(go);
删除组件
//删除组件。例如删除AudioSource组件
Destroy(GetComponent<AudioSource>());
3d物体的事件
注意:该物体需勾已选碰撞器这个组件;在Game窗口进行操作
鼠标移动进物体,在物体范围内,离开物体
//鼠标移动进物体
private void OnMouseEnter()
{
Debug.Log("Enter");
}
//鼠标在物体范围内
private void OnMouseOver()
{
Debug.Log("Over");
}
//鼠标离开物体
private void OnMouseExit()
{
Debug.Log("Exit");
}
鼠标按下,抬起,按下并抬起
//鼠标按下
private void OnMouseDown()
{
Debug.Log("Down");
}
//鼠标抬起。如果按下是在物体上,那么一出物体时,抬起是调用的
private void OnMouseUp()
{
Debug.Log("Up");
}
//按下并抬起(上面两个方法的结合)。按下并抬起必须都在物体身上
private void OnMouseUpAssButton()
{
Debug.Log("Butten")
}
按下持续调用
//按下持续调用(可用于拖拽,但拖拽更多是用射线)
private void OnMouseDrag()
{
Debug.Log("Drag");
}
碰撞体、刚体
两个物体产生碰撞的条件:两个物体都要有碰撞体,且至少一个有刚体。
注意:运行时添加的组件,在运行结束后会消失。
Unity里
代码
产生碰撞的时候会调用OnCollisionEnter
//产生碰撞的时候会调用。
/*unity里面的碰撞器是Collider,但代码中Colision是一个类,它里面包含一些数据信息。
里面可以找到碰撞器、游戏物体、刚体等。 */
private void OnCollisionEnter(Collision collision)
{
}
当碰撞结束的时候会调用OnCollisionExit
//当碰撞结束的时候会调用
private void OnCollisionExit(Collision collision)
{
Debug.Log("Exit");
}
获得碰撞的物体的碰撞器,碰撞点,碰撞法线
//产生碰撞的时候会调用。
private void OnCollisionEnter(Collision collision)
{
//获得碰撞的物体的碰撞器
Collider collider = collision.collider;
Debug.Log("Enter" + collider.name); //此时获得的是地面
//碰撞点。它是个数组,因为物体不同,碰撞点的个数不同。
Vector3 point = collision.contacts[0].point;
//碰撞法线
Vector3 normal = collision.contacts[0].normal;
}
移动物体
法一:无刚体时用。有刚体,速度特别快时,不能用(遇墙抖动)。
void Update () {
//移动物体,法一:无刚体时用。有刚体,速度特别快时,不能用。向前每秒走十米
transform.Translate(transform.forward * 10 *Time.deltaTime);
}
法二:给力Rbody.AddForce(利用刚体,只给一次力。所以速度是越来越慢的)
//移动物体,法二、法三:利用刚体
private Rigidbody Rbody;
void Start () {
//先得到物体身上的刚体组件
Rbody = GetComponent<Rigidbody>();
//法二:给力(给一次。所以速度是越来越慢的 )。方向(前方向量)* 力
Rbody.AddForce(transform .forward * 300f);
}
法三:给速度Rbody.velocity(利用刚体)
//移动物体,法二、法三:利用刚体
private Rigidbody Rbody;
void Start () {
//先得到物体身上的刚体组件
Rbody = GetComponent<Rigidbody>();
}
void Update () {
/*移动物体,法三:给速度。velocity代表当前物体的速度。
transform.forward我的前方,如果是会滚动的物体,那么它的前方是会发生改变,
所以注意是否需要锁定滚动。*/
Rbody.velocity = transform.forward * 10;
//匀速移动。Vector3.forward世界的前方,方向不会变。
Rbody.velocity = Vector3.forward * 10;
}
炸箱子
课程代码
//产生碰撞的时候会调用。
/*unity里面的碰撞器是Collider,但代码中Colision是一个类,它里面包含一些数据信息。
里面可以找到碰撞器、游戏物体、刚体等。 */
private void OnCollisionEnter(Collision collision)
{
//爆炸范围半径5m
float r = 5;
//Physics物理的类,它有很多方法,比如此处的OverlapSphere。
//得到圆心为collision.contacts[0].point,半径为r的圆中间的所有碰撞体。
Collider[] colliders = Physics.OverlapSphere(collision.contacts[0].point,r);
//在unity里面把箱子的标签统一成Box
//遍历碰撞体
foreach(Collider collider in colliders)
{
//判断是不是可以被击飞的箱子
if(collider.tag == "Box")
{
/*给箱子添加爆炸力。首先拿它的刚体GetComponent,
然后给它一个爆炸力AddExplosionForce,参数:力(50),爆炸点(圆心),半径(r)*/
collider.GetComponent<Rigidbody>().AddExplosionForce(500f, collision.contacts[0].point, r);
}
}
复习自写代码
//产生碰撞时调用
void OnCollisionEnter(Collision collision)
{
//爆炸半径
float radius = 5f;
//爆炸点
Vector3 point = collision.contacts[0].point;
//拿到要炸的物体
Collider[] colliders = Physics.OverlapSphere(point, radius);
//遍历物体,找到要炸的
for(int i = 0; i < colliders.Length; i++)
{
if (colliders[i].CompareTag("Box"))
{
//给爆炸力
colliders[i].GetComponent<Rigidbody>().AddExplosionForce(500f, point, radius);
}
}
}
触发器
下面的实例中,脚本在球上,让球穿过立方体,立方体的触发器应该打上勾。
进入触发区域调用
//进入触发区域调用。other代表你(球)进入的那个物体(立方体)的触发器
private void OnTriggerEnter(Collider other)
{
//打印触发器的名字,结果是立方体
Debug.Log("Enter" + other.name);
}
离开触发区域调用
//离开触发区域调用
private void OnTriggerExit(Collider other)
{
Debug.Log("Exit");
}
物理材质
射线
画出射线
void Start () {
//射线。射线的起始点,射线向量。从003的点向下4米的射线。
Ray ray = new Ray(Vector3.up * 3, Vector3.down * 4);
}
void Update () {
//画出射线
Debug.DrawRay(Vector3.up * 3, Vector3.down * 4);
}
检测碰撞
法一:只显示第一个碰撞点
void Start () {
//射线。射线的起始点,射线向量。从003的点向下4米的射线。
Ray ray = new Ray(Vector3.up * 3, Vector3.down * 4);
//取得射线碰撞的物体。RaycastHit碰撞数据结构体。
RaycastHit hit; //声明一个碰撞数据结构体。
/*检测射线碰撞。out的意思就是,我们把hit传进去,
它在内部可以给hit赋值,之后我们就可以把hit拿出来了。*/
bool res = Physics.Raycast(ray, out hit);
if (res == true)
{
//鼠标点在地面上。打印碰撞点(只会打印第一个碰撞点)。
//Debug.Log("鼠标点在:" + hit.point);
}
}
void Update () {
//画出射线
Debug.DrawRay(Vector3.up * 3, Vector3.down * 4);
}
}
}
法二:RaycastHit[]碰撞点的集合
void Start () {
//射线。射线的起始点,射线向量。从003的点向下4米的射线。
Ray ray = new Ray(Vector3.up * 3, Vector3.down * 4);
//取得射线碰撞的物体。RaycastHit碰撞数据结构体。
RaycastHit hit; //声明一个碰撞数据结构体。
//法二:检测射线碰撞
RaycastHit[] hits = Physics.RaycastAll(ray);
}
void Update () {
//画出射线
Debug.DrawRay(Vector3.up * 3, Vector3.down * 4);
}
}
}
鼠标点在地面上
void Update () {
if(Input.GetMouseButtonDown(0))
{
//取得射线。Camera.main主摄像机。屏幕坐标的位置
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//取得射线碰撞的物体。RaycastHit碰撞数据结构体。
RaycastHit hit; //声明一个碰撞数据结构体。
/*检测射线碰撞。
意思就是,我们把hit传进去,它在内部可以给hit赋值,之后我们就可以把hit拿出来了。*/
bool res = Physics.Raycast(ray, out hit);
if (res == true)
{
//鼠标点在地面上。打印碰撞点(只会打印第一个碰撞点)。
Debug.Log("鼠标点在:" + hit.point);
}
}
}
物体向鼠标点击的位置移动
public class ReyTest : MonoBehaviour {
//目标点traget
private Vector3 target;
void Start () {
//首先,目标点位置就是自身位置
target = transform.position;
}
// Update is called once per frame
void Update () {
if(Input.GetMouseButtonDown(0))
{
//取得射线。Camera.main主摄像机。屏幕坐标的位置
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//取得射线碰撞的物体。RaycastHit碰撞数据结构体。
RaycastHit hit; //声明一个碰撞数据结构体。
/*检测射线碰撞。out的意思就是,我们把hit传进去,
它在内部可以给hit赋值,之后我们就可以把hit拿出来了。*/
bool res = Physics.Raycast(ray, out hit, 500f,1<<LayerMask.NameToLayer("Ground"));
if (res == true)
{
//鼠标点在地面上。打印碰撞点(只会打印第一个碰撞点)。
//Debug.Log("鼠标点在:" + hit.point);
//之后,将鼠标点击的位置赋值给目标点
target = hit.point;
//如果希望Y轴不变,则等于它自身的Y值
target.y = transform.position.y;
}
//判断一下目标位置和我的位置之间的距离,如果大于0.3就向目标距离前进
if(Vector3.Distance(target,transform.position)> 0.3f)
{
//得到向量。(目标位置-我的位置),然后转换成单位向量,这样便于计算速度。
Vector3 dir = (target - transform.position).normalized;
//转向这个向量。Quaternion四元数
transform.rotation = Quaternion.LookRotation(dir);
//前进
transform.Translate(Vector3.forward * 2 * Time.deltaTime);
}
}
}
}
特别说明
法一:(ray, out hit)两个参数(会出现墙后位置不能到达的问题)
//法一:(ray, out hit)两个参数。会出现墙后位置不能到达的问题。
//检测射线碰撞。out的意思就是,我们把hit传进去,它在内部可以给hit赋值,之后我们就可以把hit拿出来了。
bool res = Physics.Raycast(ray, out hit);
法二:四个参数(指定与哪一层进行检测,解决墙后位置不能到达的问题)
参数3:射线长度是500米。参数4:第几层(层Ground在第8层)。
第四个参数:
1、左移运算符<<
2、导致两种写法:比如此处都是要检测地面。
3、第四个参数还影响着:如果不想和谁检测。
即将第四个参数用小括号括起来,前面加波浪线。例如:~(1<<8)
写法一:1<<8 查看地面是哪一层,把层数写在这里,此处为8.
/*左移运算符<<。LayerMask:1<<层数,就代表和这层进行射线检测。
如果是两层,则加|隔开,例如:1<<8 | 1<<9*/
//法一:1<<8 查看地面是哪一层,把层数写在这里,此处为8.
bool res = Physics.Raycast(ray, out hit, 500f,1<<8);
写法二:1<<LayerMask.NameToLayer(“Ground”) 直接写要检测的物体的名字,此处为地面
//法二:1<<LayerMask.NameToLayer("Ground") 直接写要检测的物体的名字,此处为地面
bool res = Physics.Raycast(ray, out hit, 500f,1<<LayerMask.NameToLayer("Ground"));