2013-12-18 27 views
1

http://answers.unity3d.com/questions/32413/using-constructors-in-unity-c.html 這不正好解決了以下問題:解決方法爲在Unity C#構造函數

  • 各種武器級別
  • 服務器 - 客戶端架構
  • 服務器要產生一個武器或彈丸,但在此之前想要設置哪個玩家射擊,武器的等級等等。
  • WeaponScript應該處理所有效果,如Instantiation自己

我能做到這一點,像這樣

GameObject fireball = (GameObject)GameObject.Instantiate(pfFireball, p.Position, p.Rotation); 
FireBall fb = (FireBall)fireball.GetComponent(typeof(FireBall)); 
fb.agressorId = pId; 
fb.weaponLevel = p.Controller.WeaponLevel; 
networkView.RPC("ShootClientWeapon", RPCMode.All, (int)w, p.PlayerId); 

但是,如果我想讓我的武器處理它們的外觀/實例化的邏輯是什麼。例如,如果我有一件武器,它的遊戲物體或者直接在每個玩家的位置產生,或者只是在agressor的位置。失敗。 我期望像...

fireball fb = new FireBall(); 
fb.gameObject = prefabFireball; 
fb.agressorId = pId; 
fb.weaponLevel = p.Controller.WeaponLevel; 
fb.Fire(); 

有沒有解決方法? 如果我讓一個類不繼承Monobehaviour,那麼我的更新方法就沒有了。但我唯一需要的是自己處理Instantiation。

回答

2

你可以有一個繼承自MonoBehavior的FireballBehavior和一個不會從任何東西繼承的Fireball對象。

你的FireballBehavior會照顧產卵和殺死火球以及跟蹤現場的情況,另一方面你的火球對象應該完全是數據驅動的,只能持有數據武器。

允許你從服務器發送消息到FireballBehavior任何遊戲對象說「實例化該對象:火球」

我是清楚了嗎?

class FireballBehavior : MonoBehavior { 

    Fireball fireball; 
    public void startFireball(Fireball frb) { 
     fireball = frb; 
     createFireball(); //instanciation and stuff 
    } 
    //your functions handling creation update and killing 

} 

class Fireball { 

    GameObject gameObject = prefabFireball; 
    Int agressorId = pId; 
    Int weaponLevel = p.Controller.WeaponLevel; 

} 

這樣,你可能只是從網絡上發送消息:

gameobject.GetComponent<FireballBehavior>().startFireball(frbFromServer); 

綜上所述行動:一個通用的行爲,根據小的數據,所有的數據做了更新和instanciation類或結構只能由服務器處理並從中發送

這種方法的優點是它可以互換,並且Fireball是一個穩定的狀態對象,您可以序列化他或將他存儲在數據庫中,而不需要太多的工作,只有幾個變化y ou可以在執行期間直接在FireballBehavior中更改Fireball對象,以便在不同時間擁有不同的火球......

這是一個從這些視頻衍生出來的想法:(不記得哪一個......但是兩個都很好手錶)

要完成你甚至可以有這個做了非常通用的方式回答:

class AnyObjectBehavior : MonoBehavior { 

    AnyObject Object1; 
    public void startFireball(anyObject frb) { 
     Object1 = frb; 
     initiateAnyObject(); //instanciation and stuff 

    } 
    //your functions handling creation update and killing 

    private void initiateAnyObject() { 

     myObjectList.add(Object1) //that way you do not have to 
            // use for loops to edit some objects 
     //instanciation stuff 
    } 

} 

class AnyObject { 
    //Generic properties 
    GameObject gameObject = prefabFireball; 

} 

class Fireball : AnyObject 
{ 
    //fireball specific properties 
    Int agressorId = pId; 
    Int weaponLevel = p.Controller.WeaponLevel; 

} 

這樣,只需要添加新的類要實例化和始終使用相同的behaviorComponent開始更新並殺死他們,甚至保持anyObject類型的所有對象的泛型列表與

任何對象類型
List<anyObject> myObjectList = new List<anyObject>() {fireball, carrot, chicken} 
+0

這是一個非常好的方法。使用非monobehaviour類引用它們的遊戲對象。 – Alex

+0

事實上(這不是我的,我將在編輯中添加源代碼),甚至可以製作這些對象的列表,以便能夠訪問它們2種方式(gameobject到火球或火球到gameobject),而無需執行foreach循環 –

+0

如果有人可以用Interfaces來改進我的答案的第二部分,這可能會是一個更好的答案(我對接口的信心還不足以繼承) –

1

幾個想法:

  1. 您可以通過使用一個虛擬的遊戲對象,簡單地調用委託在它自己的更新循環代表一個假的更新循環。

  2. 缺乏構造函數可以被認爲是一個不便之處,很容易用GameObject上的通用擴展方法解決。你可以例如有一個.Create<T>(params ...),它將基本上隱藏所有的醜陋,併爲你做實例化和初始化。

我使用了類似的方法,我的所有武器都是從完全隨機的'drop sheet'創建的,依此類推。

0

您也可以在您的自定義序列化類中實例化您不需要FireBallBehaviour。 我發現的最佳方法是製作一個自定義的序列化播放器類,它具有您的Weapon類的實例,該類有一個Ammo類的實例。

Player類可以是這個樣子:

using UnityEngine; 
using System.Collections; 
using System.Collections.Generic; 

[System.Serializable] 
public class PlayerCharacter 
{ 
    //public NetworkPlayer newtWorkPlayer; 
    public int playerID; 
    public GameObject characterObject; 
    public string characterName; 
    public float walkSpeed; 
    public int health; 
    public Vector3 spawnPosition; 

    public List<Weapon> weapons = new List<Weapon>(); 
    public Weapon equipedWeapon; 

    public PlayerCharacter() 
    { 
     playerID = 0; 
     characterObject = null; 
     characterName = ""; 
     walkSpeed = 0; 
     health = 0; 
    } 

    public PlayerCharacter(/*NetworkPlayer nP,*/ int pID, GameObject cO, string cN, float wS, int h, Vector3 sP) 
    { 
     //newtWorkPlayer = nP; 
     playerID = pID; 
     characterObject = Network.Instantiate(cO, sP, Quaternion.identity, 0)as GameObject;//GameObject.Instantiate(cO,sP,Quaternion.identity)as GameObject; 
     characterName = cN; 
     walkSpeed = wS; 
     health = h; 
     spawnPosition = sP; 
    } 

    public void TakeDamage (int takeDamage) 
    { 
     health -= takeDamage; 
    } 

    public void Movement (Vector3 target) 
    { 
     characterObject.transform.position += target; 
    } 
} 

你的武器類:

using UnityEngine; 
using System.Collections; 

[System.Serializable] 
public class Weapon 
{ 
    public GameObject weaponObject; 
    public WeaponType typeOfWeapon; 
    public Ammo ammo; 

    public Weapon (GameObject wO, WeaponType tOW, Ammo a) 
    { 
     weaponObject = wO; 
     typeOfWeapon = tOW; 
     ammo = a; 
    } 

    public void UseWeapon() 
    { 
     switch(typeOfWeapon) 
     { 
     case WeaponType.FireBall: 
      //some weapon code here 
      break; 
     case WeaponType.RidiculousHugeGun: 
      //some weapon code here 
      break; 
     case WeaponType.MegaAwesomeMagicPower: 
      //some weapon code here 
      break; 
     case WeaponType.Knife: 
      //some weapon code here 
      break; 
     } 
    } 
} 
public enum WeaponType 
{ 
    FireBall, 
    RidiculousHugeGun, 
    MegaAwesomeMagicPower, 
    Knife 
} 

你的彈藥類:

using UnityEngine; 
using System.Collections; 

[System.Serializable] 
public class Ammo 
{ 
    public GameObject ammoObject; 
    public int damage; 
    public float moveSpeed; 

    public Ammo(GameObject aO, int d, float mS) 
    { 
     ammoObject = GameObject.Instantiate(aO)as GameObject; 
     damage = d; 
     moveSpeed = mS; 
    } 
    public IEnumerator Movement (Vector3 target) 
    { 
     while(ammoObject != null) 
     { 
      ammoObject.transform.position = ammoObject.transform.forward+target*moveSpeed*Time.deltaTime; 

      yield return null; 
     } 

    } 
} 
public enum AmmoType 
{ 
    FireBallBall, 
    RidiculousHugeBullet, 
    MegaAwesomeMagicPowerEffect, 
    None 
} 

那麼你將有多數民衆贊成Monobehaviour一個的PlayerController處理所有的輸入和碰撞檢測: 我只在這裏給出一個移動示例,因爲它已經在這裏得到了很多代碼,但我想你可以想象你將如何做到這一點與武器。既然你的武器是通過播放器實例作爲player.currentWeapon或通過player.currentWeapon.ammo彈藥訪問

using UnityEngine; 
using System.Collections; 

public class PlayerController : MonoBehaviour { 

    public PlayerCharacter player; 

    void Update() 
    { 
     if(Input.GetAxis("Horizontal") != 0 || Input.GetAxis("Vertical") != 0) 
     { 
      player.Movement(new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"))*player.walkSpeed*Time.deltaTime); 
     } 
    } 
} 

在多人遊戲中玩家從遊戲服務器得到他的實例:

using UnityEngine; 
using System.Collections; 
using System.Collections.Generic; 

public class GameServer : MonoBehaviour 
{ 
    public List<PlayerCharacter> players = new List<PlayerCharacter>(); 
    private int playerCount = 0; 

    void OnPlayerConnected(NetworkPlayer player) 
    { 
     networkView.RPC("CreatePlayer", player); 
     Debug.Log("Player " + playerCount + " connected from " + player.ipAddress + ":" + player.port); 
    } 

    [RPC] 
    void CreatePlayer() 
    { 
     playerCount++; 
     PlayerCharacter playerChar = new PlayerCharacter(/*player,*/ playerCount, (GameObject)Resources.Load("Player"), "Player"+playerCount, 5, 100, Vector3.zero); 
     playerChar.characterObject.AddComponent<PlayerController>().player = playerChar; 
     players.Add(playerChar); 
    } 
} 

最後一件事// @GéryArduino:我看不出你的例子是通用的嗎?由於您正在提交實際的數據類型,因此它不是任何地方的類型安全。以供參考關於泛型讀取this