撰写了文章 发布于 2017-08-22 22:48:52
[Unity2D] 横版2D游戏开发实例三
实例1https://cowlevel.net/article/1904395
实例2https://cowlevel.net/article/1904819
上一节把人物的跳跃及移动脚本做好这一节主要是添加对应的吃金币环节以及击碎砖块
在开始前首先做一个摄像机的追踪模块之后则是金币的制作人物的碰触金币消失的环节UI的对应添加已经砖块的破碎这几点。会有点长但是基本的原理还是共通的
Camera追踪
为了实现Camera追踪人物且在场景的左右两侧实现固定而非继续移动的效果我们使用一个小技巧来简洁的实现这个功能。具体实现逻辑是在相机上挂载左右两侧的透明collider并设置相机的移动范围即可。
New Script CamerFollow挂载在Camera组件下具体代码如下
Vector2 range=new Vector2(-2f,42f);
public Transform target;//拖拽主人公至此
void Update(){
Vector3 pos=transform.pos;
pos.x=target.position.x;
pos.x=Mathf.Clamp(pos.x,range.x,range.y);
transform.pos=pos;
}
Mathf.Clamp 钳制
static float Clamp(float value, float min, float max);Description 描述
Clamps a value between a minimum float and maximum float value.
如果value小于min返回min。 如果value大于max返回max否则返回value
金币制作
按照创建主角的逻辑在空物件下挂载金币贴图的方式进行创建
添加自旋转动画以及CircleCollider2D组件勾选IsTrigger
添加硬币消失动画(CoinDamp)具体动作曲线为向上移动加速下坠并消失消失的动画通过修改Sprite.Render.Color来实现
挂载脚本CoinEater,代码如下
bool eaten=false;
void OnTriggerEnter2D(Collider2D col){
if(col.tag!="Player"||eaten){return;}
animator.Play("CoinDamp");
eaten=true;
}
void Die(){
Destroy(gameObject);
}
在CoinDamp动画的最末一帧右键选择AddAnimationEvent并选择Die()方法使动画播放完毕后自动销毁硬币组件
OnTriggerEnter&OnCollisionEnter的区别
1测试如果两个物体A,B
两者都有碰撞体colliderBox ColliderSphere ColliderCapsule Collider等
AB都有刚体Rigidbody
A或者B中有一个勾选isTrigger或者两者都勾选isTrigger A和B都可以进入OnTriggerEnter方法但是不可进入OnCollisionEnter方法。
A和B都不勾选isTriggerA和B能进入OnCollisionEnter方法但是不能进入OnTriggerEnter方法。
结论
OnCollisionEnter方法必须是在两个碰撞物体都不勾选isTrigger的前提下才能进入反之只要勾选一个isTrigger那么就能进入OnTriggerEnter方法。
OnCollisionEnter和OnTriggerEnter是冲突的不能同时存在的。
2OnTriggerEnter和OnCollisionEnter的选择。
如果想实现两个刚体物理的实际碰撞效果时候用OnCollisionEnterUnity引擎会自动处理刚体碰撞的效果。
如果想在两个物体碰撞后自己处理碰撞事件用OnTriggerEnter。
UI的效果实现
计分的UI系统照搬LoadingScene主要为左上角的积分中间硬币数及右上角的时间倒数
积分的变化与人物场景的遭遇主要通过UI下方的三段对应脚本已经挂载在UnityChan下的人物状态脚本相互回传来实现其中金币对应脚本CountCoin,积分对应CountScore倒计时对应CountScore人物状态对应脚本PlayerState。以下是对应代码
PlayerState
public int coins=0;
public int amount=0;
void CoinPlus(int num){
coins+=num;
}
//ScorePlus方法使用的是方法调用与CoinPlus方法行程鲜明反差这个做法的优点在于避免之后的事件处理均放在Update方法下节省资源
void ScorePlus(int num){
amount+=num;
ScoreUI.SendMessage("ScoreUpdate");
}
CountCoin
//直接放置在Update方法下处理若组件较多容易占用资源
void Update(){
int amount=GameObject.FindWithTag("Player").GetComponent<PlayerState>().coins;
GetComponent<Text>().text="X"+((amount>9)?(amount.ToString()):("0"+amount));//判断金币数是否为2位数若为个位数则手动在数字前面添加0
}
CountScore
//通过方法调用来实现节省资源
void ScoreUpdate(){
int amount=GameObject.FindWithTag("Player".GetComponent<PlayerState>().amount;)
string number=amount+"";//转义为字符串形式
string zero="000000";
GetComponent<Text>().text=zero.Sustring(0,zero.Length-number.Length)+amount;
}
SubString(startindex,length)
从index个字符开始截取长度为length的字符串此处即是指从6个0的字符串中截取出去除掉分数本身长度的0并与回传的积分相组合构成开头为0的总分数
CountTime
public int maxTime=120;
int currentTime=0;
void Start(){
currentTime=maxTime;
InvokeRepeating("CountDown",0,1);
}
void CountDown(){
currentTime-=1;
GetComponent<Text>().text="Time\n"+currentTime;
}
创建可破坏砖块
既然是要做可以破坏的砖块那么必然是要替换一些砖块为特殊的贴图并挂载对应脚本且添加砖块破碎的动画。
创建砖块部分较为简单在此不做详述。注意后期完成后可以直接生成Prefabs批量构建
添加砖块破碎动画
按照同样地砖块创建方法空物件下挂载4块碎片坐标统一归0。
创建Animation→Broken拖拽到破碎方块的Animation中并在动画中实现4块砖块分别向4个方向散开的动画。在最后一帧添加AnimationEvent并调用Die()方法在动画播放完毕后销毁
破碎砖块实例化
Unity中有几个文件夹是比较特殊的其中我们要用到的就是名称为Resources的文件夹。通过把资源放置在该文件夹下可以动态加载资源很适用于诸如子弹发射、特效之类的非常驻类型。
把我们刚才创建好的BrokenBlock直接拖拽到Resources文件夹中即可
在砖块中挂载BrokenBlock脚本代码如下
void OnCollisionEnter2D(Collision2D col){
if(col.gameObject.tag=="Player"&&col.contacts[0].normal==Vector2.up){
GameObject broken=Instantiate(Resources.Load("Broken"),transform.position,transform.rotation) as GameObject;
if(Random.value>0.5f){//随机生成碎片
Instantiate(Resources.Load("Coin"),transform.position,transform.rotation)
}
Destroy(gameObject);
}
}
Object.Instantiate 实例化
C# ⇒ static Object Instantiate(Object original, Vector3 position, Quaternion rotation);
Parameters
original An existing object that you want to make a copy of. position Position for the new object. rotation Orientation of the new object. Description
Clones the object original and returns the clone.
Resources.Load 加载
C# ⇒ public static Object Load(string path);Description 描述
Loads an asset stored at path in a Resources folder.Returns the asset at path if it can be found otherwise returns null. Only objects of type will be returned if this parameter is supplied. The path is relative to any Resources folder inside the Assets folder of your project, extensions must be omitted.
目录