github传送门:https://github.com/dongzizhu/unity3DLearning/tree/master/hw5/enhancedDisk

有关Rigibody

Rigidbody是Unity自带的物理引擎中的刚体组件,可以直接通过Add Component添加。

unity skin bone 数量_unity3d

我们能够通过这个组件来让Object按照真实的物理规律运动。其中属性的含义以此是

  • Mass 质量
  • Drag 阻力
  • Angular Drag 角阻力
  • Use Gravity 使用重力
  • Is Kinematic 是否运动学控制
  • Interpolate 差值
  • Collision Detection 碰撞检测
  • Constraints 运动的自由度
  • Info 运动的信息

本次完成的打飞碟小游戏升级版就应用到了Rigidbody来实现飞碟符合物理规律的运动。

Adapter模式

Adapter模式又称适配器模式,就是定义一个Adapter类,起到一个转换插头的作用,将原本不能用统一的代码来调用的多个类转换成成一样的接口,这样可以统一调用,是一种封装的常用做法。在本次的项目中,我们将物理模式和上一个版本的直接发射模式的两种AcitionManager都接上Adapter这个转换插头,然后在ActionManager中统一调用。

有关这个设计模式的具体讲解见链接:http://c.biancheng.net/view/1361.html,这个说的很清楚了。

打飞碟小游戏升级版

在上次时间直接位移的Emit.cs 后,这次我们利用Rigidbody来实现一个符合物理规律的移动方法。

// PhysicsEmit.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyGame;

public class PhysicsEmit : SSAction
{
    bool enableEmit = true;
    Vector3 force;
    float startX;
    float targetZ = 50;
    public FirstController sceneControler = (FirstController)Director.getInstance().sceneCtrl;
    
    public override void Start() {
        startX = 6 - Random.value * 12;
        this.Transform.position = new Vector3(startX, 0, 0);
		force = new Vector3(3 * Random.Range(-1, 1), 3 * Random.Range(0.5f, 5), 5 + 3 * sceneControler.user.round);
    }
	
    public static PhysicsEmit GetSSAction() {
        PhysicsEmit action = ScriptableObject.CreateInstance<PhysicsEmit>();
        return action;
    }
    
    public override void Update() {
        if (!this.destroy) {
            if (enableEmit) {
	            GameObject.GetComponent<Rigidbody>().useGravity = true;
                GameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;
                GameObject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);
                enableEmit = false;
            }
        }
        if (this.Transform.position.z >= targetZ || GameObject.GetComponent<DiskController>().hit) {
            GameObject.SetActive(false);
			GameObject.transform.position = new Vector3(startX, 0, 0);
			sceneControler.factory.freeDisk(GameObject);
			this.destroy = true;
			this.Callback.ActionDone(this);
			GameObject.GetComponent<DiskController>().hit = false;
        }
    }
    
}

其中核心的部分就是一下三句。

GameObject.GetComponent<Rigidbody>().useGravity = true;
GameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;
GameObject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);

第一句将useGravity设为true,那么当前GameObject就会一直受到一个向下的重力;第二句,将当前的GameObject的速度重置为0,因为是从工厂模式的free队列中取出来的,所以如果不置零则会保留之前的速度;最后一句通过AddForce给当前物体加上一个瞬间的力从而给予其一个初始速度。

其中ForceMode一共有四种:

  • ForceMode.Force:给物体添加一个持续的力并使用其质量。
  • ForceMode.Acceleration::给物体添加一个持续的加速度,但是忽略其质量。
  • ForceMode.Impulse;:给物体添加一个瞬间的力并使用其质量
  • ForceMode.VelocityChange;:给物体添加一个瞬间的加速度,但是忽略其质量

另外,Adapter的代码如下:

public class ActionManagerAdapter {
    ActionManager normalAM;
    PhysicsActionManager PhysicsAM;

    public int mode = 0; // 0->normal, 1->physics

    public ActionManagerAdapter(GameObject main) {
        normalAM = main.AddComponent<ActionManager>();
        PhysicsAM = main.AddComponent<PhysicsActionManager>();
        mode = 0;
    }

    public void SwitchActionMode() {
        mode = 1 - mode;
    }

    public void PlayDisk(int round) {
        if (mode == 0) {
            Debug.Log("normalAM");
            normalAM.playDisk(round);
        }
        else {
            Debug.Log("physicsAM");
            PhysicsAM.playDisk(round);
        }
    }

    public void SetNormalAM(ActionManager am) {
        normalAM = am;
    }

    public void SetPhysicsAM(PhysicsActionManager pam) {
        PhysicsAM = pam;
    }

    public ActionManager GetNormalAM() {
        return normalAM;
    }

    public PhysicsActionManager GetPhysicsAM() {
        return PhysicsAM;
    }
}

这样在firstConctrl调用playDisk的时候,由Adapter根据此时的mode来选择射出的飞碟是什么模式的;这样来将两种飞碟封装起来,实现统一调用。

其他的改动就是增加一个PhysicsActionManager,代码与原来的ActionManager几乎一样,只不过是调用了PhysicsEmit来执行Action而已;然后在FirstController以及一些其他的地方将ActionManager改为Adapter。这里代码就不贴上来了,感兴趣的可以去github上查看。