2016-08-29 7 views
-1

今、Spheresを作成しているときに、右の階層にすべてが表示されます。 が、私はそれがすべての球を拡大する地形をクリックします場合にのみ、その地形の内部/の下でそれらを見ることにしたい:階層内の作成されたすべてのSpheresオブジェクトを地形の下に置くにはどうすればよいですか?

Spheres

私はすべての100球を表示したくありません地形の下に/地形を置くか、他のGameObjectの下に置くようにします。それをクリックすると、左側の階層にあるすべての100の球体が展開されます。

これはスクリプトです:シーン内のすべてのゲームオブジェクトを通じて

using System; 
using UnityEngine; 
using Random = UnityEngine.Random; 

[ExecuteInEditMode] 
public class SphereBuilder : MonoBehaviour 
{ 
    // for tracking properties change 
    private Vector3 _extents; 
    private int _sphereCount; 
    private float _sphereSize; 

    /// <summary> 
    ///  How far to place spheres randomly. 
    /// </summary> 
    public Vector3 Extents; 

    /// <summary> 
    ///  How many spheres wanted. 
    /// </summary> 
    public int SphereCount; 

    public float SphereSize; 

    private void OnValidate() 
    { 
     // prevent wrong values to be entered 
     Extents = new Vector3(Mathf.Max(0.0f, Extents.x), Mathf.Max(0.0f, Extents.y), Mathf.Max(0.0f, Extents.z)); 
     SphereCount = Mathf.Max(0, SphereCount); 
     SphereSize = Mathf.Max(0.0f, SphereSize); 
    } 

    private void Reset() 
    { 
     Extents = new Vector3(250.0f, 20.0f, 250.0f); 
     SphereCount = 100; 
     SphereSize = 20.0f; 
    } 

    private void Update() 
    { 
     UpdateSpheres(); 
    } 

    private void UpdateSpheres() 
    { 
     if (Extents == _extents && SphereCount == _sphereCount && Mathf.Approximately(SphereSize, _sphereSize)) 
      return; 

     // cleanup 
     var spheres = GameObject.FindGameObjectsWithTag("Sphere"); 
     foreach (var t in spheres) 
     { 
      if (Application.isEditor) 
      { 
       DestroyImmediate(t); 
      } 
      else 
      { 
       Destroy(t); 
      } 
     } 

     var withTag = GameObject.FindWithTag("Terrain"); 
     if (withTag == null) 
      throw new InvalidOperationException("Terrain not found"); 

     for (var i = 0; i < SphereCount; i++) 
     { 
      var o = GameObject.CreatePrimitive(PrimitiveType.Sphere); 
      o.tag = "Sphere"; 
      o.transform.localScale = new Vector3(SphereSize, SphereSize, SphereSize); 

      // get random position 
      var x = Random.Range(-Extents.x, Extents.x); 
      var y = Extents.y; // sphere altitude relative to terrain below 
      var z = Random.Range(-Extents.z, Extents.z); 

      // now send a ray down terrain to adjust Y according terrain below 
      var height = 10000.0f; // should be higher than highest terrain altitude 
      var origin = new Vector3(x, height, z); 
      var ray = new Ray(origin, Vector3.down); 
      RaycastHit hit; 
      var maxDistance = 20000.0f; 
      var nameToLayer = LayerMask.NameToLayer("Terrain"); 
      var layerMask = 1 << nameToLayer; 
      if (Physics.Raycast(ray, out hit, maxDistance, layerMask)) 
      { 
       var distance = hit.distance; 
       y = height - distance + y; // adjust 
      } 
      else 
      { 
       Debug.LogWarning("Terrain not hit, using default height !"); 
      } 

      // place ! 
      o.transform.position = new Vector3(x, y, z); 
     } 

     _extents = Extents; 
     _sphereCount = SphereCount; 
     _sphereSize = SphereSize; 
    } 
} 
+1

whateverGO.ransform.parent =他のGO.transform;エディタで階層を作成します。これにより、LocalScaleも問題になります。 BTWはDestroyImmediateを監視して、次のフレームには何の保証もありません(小さなテストアプリケーションを作成し、GOのヌルステータスをチェックします)ので、TBHは普通の古いDestroyと違って見つかりませんでした –

+1

@マークそれを答えに適応させる価値があるかもしれません - 私はOPのニーズを満たすのに十分なものだと思います。 – Serlite

+0

球体を地形の下に置く方法を見つけました:o.transform.parent = GameObject.Find( "Terrain")。しかし、DestroyImmediateでは、私はそれに精通していません。私はそれをどうやってやりますか? –

答えて

1

ループ、そして彼らの名前が球体である場合の地形とその親を設定します。

void Start() 
{ 
    GameObject terrain = GameObject.Find("Terrain"); 
    foreach (var obj in FindObjectsOfType(typeof(GameObject)) as GameObject[]) 
    { 
     if(obj.name == "sphere") 
      obj.transform.parent = terrain; 
    } 
} 
+0

Xanderの小さな変更点:代わりに "球体"にする必要があります "球体"と私はUpdateSpheres()関数を呼び出した後、このコードをUpdate()関数で追加しました。私はそれを動作させません開始機能に入れた場合。 –

+0

この関数を控えめに使うべきです。 'Find'関数はかなりリソースを消費します。オブジェクトが 'インスタンス化されているので、' Update() 'が必要な場合は、オブジェクトが'インスタンス化されているときのみ '親を設定し、' start'関数に 'terrain'変数を入れてその行を一度実行するだけです。 –

関連する問題