改进飞碟(Hit UFO)游戏
更新内容
为飞碟添加刚体组件,运用物理引擎来实现飞行
添加PhysicActionManager和CCPhysicEmit来实现物理运动
根据适配器模式的概念,完全可以用SSActionManager做适配器,所以PhysicActionManager要继承SSActionManager
CCPhysicEmit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using UnityEngine;
using System.Collections;
public class CCPhysicEmit: SSAction
{
public FirstController sceneController;
public static CCPhysicEmit GetSSAction()
{
return ScriptableObject.CreateInstance<CCPhysicEmit>();
}
// Use this for initialization
public override void Start()
{
sceneController = (FirstController)SSDirector.Instance.currentSceneController;
int round = sceneController.round;
if (round % 2 == 0) {
round /= 2;
}
//添加Rigidbody组件,根据round设置force的大小
var rig = gameobject.AddComponent(typeof(Rigidbody)) as Rigidbody;
rig.velocity = Vector3.zero; //将速度置为0,力清空
rig.AddForce (new Vector3 (Random.Range(-10f,10f),round,round*3), ForceMode.Impulse);
}
public override void Update() {
//若此飞碟已经回收,则回调
if (!gameobject.activeSelf) {
this.destroy = true;
this.callback.SSActionEvent (this);
} else {
//如果超出了边界-10,回收、回调
if (this.transform.position.y < -10)
{
if (sceneController.round % 2 == 0) {
if (sceneController.flag) {
sceneController.onFlying = false;
sceneController.flag = false;
} else
sceneController.flag = true;
} else {
sceneController.onFlying = false;
}
DiskFactory.instance.freeDisk (this.gameobject);
this.destroy = true;
this.enable = false;
this.callback.SSActionEvent(this);
}
}
}
}
打靶游戏
游戏内容
无限trials,但是风力会递增
最内层环5分,最外层环1分,脱靶没分
从鼠标点击位置射出箭,箭射到靶子上后颤动0.1秒
游戏架构
MVC架构,包含导演,场记。
门面模式, UserGUI类
动作分离,运用动作管理器,定义了emit和tremble动作
画面实现
靶子:五个Cylinder,越小的Cylinder越靠前
箭:一个Empty游戏对象,有四个子对象,一个Cylinder(箭杆),一个Sphere(箭尖),两个Cube(尾翼)
物理引擎的运用
为靶子添加碰撞核(Collider),但是不用触发(isTrigger = false)
为箭的Empty对象添加刚体(RigidBody)组件,并且将重力取消(gravity = false),默认为运动学(isKinematic = true),当箭在力的作用下飞行时,(isKinematic = false)
为箭的子对象箭头(Sphere)添加碰撞核,设置触发(isTrigger = true),添加脚本,监听碰撞的触发(void OnTriggerEnter(Collider c){}),碰撞时,要将Empty刚体组件的运动学取消(isKinematic = true)来停止箭的运动
ArrowCollider
挂载到箭头上(Empty的Sphere),监听碰撞事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using UnityEngine;
using System.Collections;
public class ArrowCollider : MonoBehaviour
{
public ShootingController sceneController;
// Use this for initialization
void Start ()
{
sceneController = SSDirector.Instance.currentSceneController as ShootingController;
}
void OnTriggerEnter(Collider c) {
gameObject.transform.parent.transform.GetComponent<Rigidbody>().isKinematic = true;
gameObject.SetActive(false); //将箭头(Empty的Sphere)设置不在活动,在动作管理时可以用来判断是否已发生碰撞
int score = 5 - int.Parse (c.gameObject.name); //根据环数记分,直接让场记记分
sceneController.Count (score);
}
}
SceneController
单纯地用来加载资源,动作由动作管理器来实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void LoadResources() {
for (int i = 0; i < 5; i++) {
var ring = GameObject.Instantiate<GameObject> (Resources.Load<GameObject> ("Prefabs/ring"));
ring.name = i.ToString (); //根据环数起名字
// 设置交替的颜色
if (i % 2 == 0) {
ring.GetComponent<Renderer> ().material.color = Color.red;
} else {
ring.GetComponent<Renderer> ().material.color = Color.white;
}
// 位置,大小。(小的环要更靠近相机,来成功实现碰撞触发)
ring.transform.position += new Vector3 (0,0,i*0.01f);
ring.transform.localScale = new Vector3 (i+1,1,i+1);
}
// 只维护一支箭,将箭头找出来,单独存储
arrow = GameObject.Instantiate<GameObject> (Resources.Load<GameObject> ("Prefabs/arrow"));
head = arrow.GetComponentsInChildren<Transform> () [4].gameObject;
}
CCActionManager
检测到鼠标点击时,管理箭执行发射动作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 回调函数实现箭飞行结束,射到靶子上时颤动
public void SSActionEvent(SSAction source,
SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0,
string strParam = null,
System.Object objectParam = null) {
if(objectParam != null)
{
arrowTremble = CCArrowTremble.GetSSAction();
this.RunAction(objectParam as GameObject, arrowTremble, this);
}
}
protected new void Update () {
if (Input.GetMouseButtonDown(0))
flag = true;
else if (Input.GetMouseButtonUp(0) && flag) {
sceneController.count++; // 场记维护了发射箭数目的变量
arrowEmit = CCArrowEmit.GetSSAction();
this.RunAction (sceneController.arrow, arrowEmit, this);
}
base.Update();
}
CCArrowEmit
发射动作的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using UnityEngine;
using System.Collections;
public class CCArrowEmit: SSAction
{
public ShootingController sceneController;
public static CCArrowEmit GetSSAction()
{
return ScriptableObject.CreateInstance<CCArrowEmit>();
}
// Use this for initialization
public override void Start()
{
sceneController = (ShootingController)SSDirector.Instance.currentSceneController;
var d = Camera.main.ScreenPointToRay (Input.mousePosition).direction; //根据射线找到鼠标点击的方向
sceneController.head.SetActive (true); // 激活箭头
gameobject.SetActive (true); // 激活箭
// 设置箭的位置和朝向(rotation)
transform.position = new Vector3(d.x,d.y+1,0);
transform.rotation = Quaternion.Euler(90,0,0);
// 设置刚体的属性
var rig = gameobject.GetComponent<Rigidbody>() as Rigidbody;
rig.isKinematic = false; // 关闭运动学,使力发生作用
rig.velocity = Vector3.zero; // 将原来的力及其速度清零
rig.AddForce (d*30, ForceMode.Impulse); // 根据方向添加力,和风力
rig.AddForce (sceneController.wind, ForceMode.Impulse);
}
public override void Update() {
//根据箭头是否Active来判断是否以触发碰撞
if (sceneController.head.activeSelf) {
// 如果箭已经脱靶,结束飞行
if (transform.position.z > 8) {
transform.position = Vector3.up;
sceneController.head.SetActive (false);
gameobject.SetActive (false);
this.callback.SSActionEvent (this); // 回调,参数objectParam为默认值null
}
} else {
// 完成飞行,打开运动学
var rig = gameobject.GetComponent<Rigidbody>() as Rigidbody;
rig.isKinematic = true;
this.destroy = true;
this.callback.SSActionEvent (this,objectParam:gameobject);
}
}
}
CCArrowTremble
颤抖动作的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using UnityEngine;
using System.Collections;
public class CCArrowTremble: SSAction
{
public ShootingController sceneController;
private float leftTime = 0.1f; // 颤抖时长
private Vector3 trueLocation; // 原始位置
public static CCArrowTremble GetSSAction()
{
return ScriptableObject.CreateInstance<CCArrowTremble>();
}
// Use this for initialization
public override void Start()
{
sceneController = (ShootingController)SSDirector.Instance.currentSceneController;
trueLocation = transform.position;
}
public override void Update() {
leftTime -= Time.deltaTime; // 计时
if (leftTime < 0) {
transform.position = trueLocation;
this.destroy = true;
this.callback.SSActionEvent (this);
} else {
transform.position += Vector3.left * Random.Range (-0.1f,0.1f); // 左右颤动
}
}
}