Unity项目之Ruby’Advebture笔记
unity碰撞判定逻辑(此次为标签判断)
OnTriggerEnter函数是每一帧进入碰撞体积的物体都会予以判定。通过标签判断碰撞需要销毁的物体,不发生销毁就返回空值即可。
1、两个物体都必须有碰撞器(Collider)组件;
2、其中一个物体的碰撞器(Collider)的IsTrigger属性必须勾上;
3、最重要的一点,其中一个物体必须有刚体(Rigidbody)组件。如果是一个运动的物体(如主角)去碰撞一个静止的物体,则刚体(Rigidbody)组件必须加在运动的物体上,否则无法触发OnOnTriggerEnter函数。所以这时候主角身上就要加一个Rigidboyd。
Bug描述:游戏主角在静止状态下,一个自动运动的敌人碰撞主角,如果敌人身上没有刚体(Rigidbody)组件,主角则不会受到伤害(不会执OnTriggerEnter函数中的代码)。
就是发生碰撞的主体一定是要带刚体的,即只有带刚体的碰撞体去撞其他碰撞体时,双方才会收到碰撞事件,比如:
一、控制A(刚体加碰撞体)撞击 静止的B(只有碰撞体),双方能收到碰撞事件。
二、控制B(只有碰撞体)撞击 静止的A(刚体加碰撞体),双方收不到碰撞事件。
三、让A(刚体加碰撞体)自由下落,然后控制B(只有碰撞体)去撞击A,双方能受到碰撞事件。
此外还有两点:
一、产生触发事件的两个物体会相互穿越,isTrigger检测的是可穿越碰撞,准确的说是因为开启IsTrigger那个物体会被物理引擎锁忽略掉,所以会产生两个物体穿越的情况。如果人物有Rigidbody,而且想让人物和地面产生碰撞事件且不穿过地面,可以不勾选isTrigger,用OnCollisionEnter(Collision collison)检测碰撞。
二、两个对象要么都收到碰撞事件,要么都收到触发事件,不会出现一个收到触发事件,一个收到碰撞事件的情况。
本次的项目的相关代码可如下:
//标签碰撞,需要勾选isTrigger
private void OnTriggerEnter2D(Collider2D collision)
{
PlayerController pc = collision.GetComponent<PlayerController>();
if (collision.tag == "player")
{
Debug.Log("碰到了草莓");
if (pc.MycurrentHealth < pc.MymaxHealth)
{
pc.changeHealth(1);
Destroy(this.gameObject);
}
}
}
2D平面移动方法
主角利用刚体进行移动:
void Update()
{
//移动,利用刚体移动解决抖动问题
float moveX = Input.GetAxisRaw("Horizontal");//水平方向,A=-1,D=1
float moveY = Input.GetAxisRaw("Vertical");//垂直方向,W=1,S=-1
Vector2 pos = rbody.position;
pos.x += moveX * speed * Time.deltaTime;
pos.y += moveY * speed * Time.deltaTime;
rbody.MovePosition(pos);
}
后续有更新为通过向量来进行移动:
//根据移动向量来为玩家方向赋值
Vector2 moveVector = new Vector2(moveX, moveY);
//通过向量来进行pos的加减
pos += moveVector * speed * Time.deltaTime;
rbody.MovePosition(pos);
刚体移动还需要勾选固定z轴,防止旋转如图:
摄像机逻辑以及跟随方法
希望摄像机跟随主角走,即相对静止。在start里面,外卖需要用摄像机位置减去主角位置获得三维向量,接着每一帧让摄像机位置等于主角位置加上三维向量,摄像机位置便等于主角新位置加上这个差值。相对静止。
- 官方Cinemachine插件:
首先从unity中的window中的package manage中添加Cinemachine插件,完成后如图:
并且在Cinemachine菜单中创建相关相机;之后相关相机如下:
其他follow为跟随,需要将跟随的物体进行挂上便能进行相机跟随。
相机的边缘检测需要添加Cinemachine Confiner组件,并且创建一个空物体来进行Polygon Collider的存放:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dZ8dHaHL-1630830034180)(C:\Users\86136\Desktop\Typora笔记\Unity笔记图片\11.png)]
即可实现边缘检测,超出边缘不可见
Unity TileMap工具教程
在Project目录下找到我们需要用到的素材。
图集:
接下来对素材进行处理。因为我们要切割该素材,所以需要将SpriteMode改为Multiple。素材每个格子尺寸为64,PixelsPerUnit改为64。然后选择SpriteEditor切割素材。
然后点击slice进行设置如图,最后点击slice切割完成:
接着选择Window下2D中的TilePalette打开调色板,默认是自带的调色板,我们可以选择CreateNewPalette创建自定义调色板。创建好后拖入我们之前准备的素材。
快捷栏上的功能分别是选中、移动、笔刷、矩形工具、取色橡、皮擦油、漆桶,和PS上差不多自己试下就知道了。
如果要调整Palette需要勾选Edit,要注意编辑完需要取消Edit的选中。
下面的
窗口的底部是CanChangeZPosition,勾选后允许编辑切片的 Z 轴值,当在 Z 作为 Y 平铺图上绘画时,该值可用于调整切片高度。
TilemapCollider2D
此插件为给所有的Tilemap组件添加Collider2D
添加之后Tilemap素材夹中的文件都带有Collider2D组件
且其针对精灵类型:
若想取消则将类型改为none。
Composite Collider2D组件为合并一定区域的碰撞体,进行优化。
未优化前:
先进行collide2D进行选择Used By Composite合并并优化:
优化后:
优化后可以节省内存
物体的碰撞检测两种方法
OnCollisionEnter2D和OnTriggerEnter2D两种碰撞触发
一:产生碰撞的条件
1:若要产生碰撞,必须双方都要有碰撞器。
2:运动的一方一定要有刚体,另一方有无刚体无所谓,但需要注意的是如果是静止的物体带刚体,一开始效果跟运动的物体带刚体一样,但由于刚体放在静止的物体上会休眠,所以一般要将刚体放在运动的物体身上。简而言之就是至少要有一方有刚体,一般为运动方。
注:如果运动的一方无刚体,它去碰撞静止的不带刚体的物体,相当于没有撞上,即使双方带碰撞体也会相互穿过。如果运动的一方有刚体,它去碰静止的不带刚体的物体,则该物体不会因为被碰撞而发生移动。
总的来说,如果想要两个物体碰撞后都有因为物理演算而发生位移,则双方都要有刚体和碰撞器。
二:接触的两种方式
1:Collision碰撞,造成物理碰撞,可以在碰撞时执行OnCollision事件。
2:Trigger触发,取消所有的物理碰撞,可以在触发时执行OnTrigger事件。
注:两个物体接触不可能同时产生碰撞+接触,最多产生一种。但是可以AB产生碰撞,AC产生触发。
三:产生不同方式接触的条件
1:Collision碰撞
(1):双方都有碰撞体
(2):运动的一方必须有刚体
(3):双方不可同时勾选Kinematic运动学。
(4):双方都不可勾选Trigger触发器。
2:Trigger触发
(1):双方都有碰撞体
(2):运动的一方必须是刚体
(3):至少一方勾选Trigger触发器
例如子弹碰撞脚本和草莓脚本:
//子弹
private void OnCollisionEnter2D(Collision2D collision)
{
EnemyController ec = collision.gameObject.GetComponent<EnemyController>();
if (ec != null)
{
ec.Fiexd();
Audiomanager.instance.audioplay(bulletclip);
}
Destroy(gameObject);
}
//草莓
//标签碰撞,需要勾选isTrigger
private void OnTriggerEnter2D(Collider2D collision)
{
PlayerController pc = collision.GetComponent<PlayerController>();
if (collision.tag == "player")
{
Debug.Log("碰到了草莓");
if (pc.MycurrentHealth < pc.MymaxHealth)
{
//生成特效
Instantiate(strawEffect, transform.position, Quaternion.identity);
pc.ChangeHealth(1);
Audiomanager.instance.audioplay(collectclip);//播放音效
Destroy(this.gameObject);
}
}
}
脚本的私有变量获取方法(安全性)
如PlayerController中的:
private int maxHealth = 5;//最大生命值
private int currentHealth;//当前生命中
//获取私有属性方法
public int MymaxHealth{ get{ return maxHealth; } }
public int MycurrentHealth{ get{ return currentHealth; } }
Unity基础之场景转换和退出游戏 Scnen切换
1.添加:using UnityEngine.SceneManagement;
2.调用:SceneManager.LoadScene("",LoadSceneMode.Single);"" 可以是场景名字
3.单纯转换场景用 SceneManager.LoadScene("__");
Unity基础之场景转换和退出游戏 Scnen切换
1.添加:using UnityEngine.SceneManagement;
2.调用:SceneManager.LoadScene("",LoadSceneMode.Single);"" 可以是场景名字
3.单纯转换场景用 SceneManager.LoadScene("__");
4.退出游戏: 调用:Application.Quit();