[Unity3D] 多人游戲中以角色為中心釋放沖擊波

關鍵詞:SphereCollider,ClientRpc,Command

基本思路:為角色添加Sphere Collider,通過腳本其體積和碰撞事件,實現(xiàn)沖擊效果。


Tips:

官網(wǎng)有很好的關于多人游戲的入門教程,非常值得一看:https://unity3d.com/learn/tutorials/s/multiplayer-networking


1 為角色添加額外的碰撞器,Sphere Collider, 勾選isTrigger,center可根據(jù)實際模型調(diào)整至中心位置。
2 重寫OnStartLocalPlayer(),
public class PlayerControl : NetworkBehaviour {
    
    // 啟用生成本地角色時,可以修改一些屬性值
    public override void OnStartLocalPlayer()
    {
        // 將本地角色改為藍色,便于區(qū)分,默認為白色
        GetComponent<MeshRenderer>().material.color = Color.blue;
        
        // 重設SphereCollider的半徑,將其縮小至角色體內(nèi)
        GetComponent<SphereCollider>().radius = 0.4f;

    }
}
3 沖擊波碰撞和特效的實現(xiàn)
public class Spells : NetworkBehaviour {
    
    // [SerializeField] 可以讓私有變量在editor中可見,便于測試;
    [SerializeField] private bool m_BombStart = false;
    private SphereCollider m_SphCollider;
    private float maxRadius;
    
    void Start () {
        m_SphCollider = GetComponent<SphereCollider>();
        // maxRadius 用來設置沖擊波的最大半徑
        maxRadius = m_SphCollider.radius * 10f;
    }
    
    // 法術釋放后,控制SphereCollider隨時間擴大半徑
    // 放在FixedUpdate()中,可以使半徑增加的速度,在不同性能的機器上保持一致。
    void FixedUpdate(){
        if(!isLocalPlayer){
            return;
        }
        
        // m_BombStart 用來控制開始和結(jié)束
        if(m_BombStart){
            
            if (m_SphCollider.radius < maxRadius) {
                m_SphCollider.radius += 0.2f;
            } else {
                // 半徑達到最大后,重置半徑,并停止半徑繼續(xù)增加。
                m_SphCollider.radius = 0.4f;
                m_BombStart = false;
            }
            
        }
    }
    
    // 沖擊波,在PlayerControl.cs中,通過按鈕調(diào)用
    public void Bomb(int groupindex){
        // groupindex 區(qū)分法術類型,不同類法術設置不同CD,
        if (!CD_Trigger[groupindex]) {
            
            // 下個FixedUpdate Frame開始增加SphereCollider的半徑;
            m_BombStart = true;
            // 開啟冷卻計時;
            CDTrigger(groupindex);
            // 在角色位置,調(diào)用施法效果;
            CmdBombEffect(transform.position);
        }
    }
    
    // 沖擊波碰撞效果實現(xiàn)
    void OnTriggerEnter(Collider other){
        // if條件確保只有非本地角色,才會受到由本地角色所釋放的沖擊波法術的影響
        if (other.CompareTag ("Player") && 
            !other.GetComponent<NetworkIdentity> ().isLocalPlayer) {
            // 計算沖擊方向
            var bounceDir = other.transform.position - transform.position;
            
            // 直接調(diào)用下面這條語句,在多人游戲中不能實現(xiàn)預期效果,
            // 因為本地雖然更改了角色的位置,但服務器端卻沒有,
            // 因此只會看到角色受力后,被服務器迅速重置到之前的位置,最終只會有一個微小的抖動。
            // other.attachedRigidbody.AddForce (bounceDir * 500f);
            
            // 正確的做法是讓服務器,通知所有客戶端來執(zhí)行這個動作
            CmdBomb (bounceDir,other.gameObject);

        }
    }
    // 簡單理解,就是向服務器發(fā)出一條指令,由服務器來執(zhí)行 (具體可參考API和開頭給出的教程)
    [Command]
    void CmdBomb(Vector3 dir,GameObject other){
        RpcBomb(dir,other);
    }
    
    // 簡單理解,就是從服務器發(fā)出一條指令,在所有客戶端上執(zhí)行
    [ClientRpc]
    void RpcBomb(Vector3 dir,GameObject other){     
        // 實現(xiàn)角色受到?jīng)_擊的效果
        other.GetComponent<Rigidbody>().AddForce (dir * 500f);
    }
    
    // 同理,這個是用來觸發(fā)沖擊波特效的,如果不通過服務器給所有客戶端發(fā)指令,那么只能在本機看到,其他客戶端則看不到。
    [Command]
    void CmdBombEffect(Vector3 bombcenter){
        RpcBombEffect(bombcenter);
    }
    
    [ClientRpc]
    void RpcBombEffect(Vector3 bombcenter){     
        // 保存在EffectsManager.Instance.hitEffects中的一個本地粒子效果
        var clone = (GameObject)Instantiate (EffectsManager.Instance.hitEffects[1], bombcenter, Quaternion.identity);
        Destroy (clone,2f);
    }

}
4 實現(xiàn)效果

(藍色是本機,白色是另一個玩家。畫面有點渣,各位看官見諒,不懂美術的程序員,目前只能這樣了。。。)


沖擊波.gif
Enjoy It!
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容