前回の続き。
Terrain の上に 木を配置するチュートリアルをやってみました。
Planeの生成時に配置する木は、あらかじめ生成しておいた中からプーリングして使い回す…という内容です。
木のプーリングは 新たに “TreePool” という GameObject を配置し、以下のScriptをアタッチします。
using System.Collections; using System.Collections.Generic; using UnityEngine; //using System.Linq; public class TreePool : MonoBehaviour { static int numTree = 1000; static GameObject[] trees; [SerializeField] GameObject treePrefab; // Use this for initialization void Awake () { TreePool.trees = new GameObject[TreePool.numTree]; for (int i = 0; i < TreePool.trees.Length; i++) { var tree = Instantiate (this.treePrefab, Vector3.zero, Quaternion.identity) as GameObject; tree.SetActive (false); TreePool.trees [i] = tree; } } static public GameObject getTree() { // //LINQ 例 (Terrainのつなぎ目がおかしくなる...原因はわからない) // var count = TreePool.trees.Count (t => !t.activeSelf); // if (count > 0) { // var tree = TreePool.trees.First(t => !t.activeSelf); // return tree; // } // // return null; for (int i = 0; i < TreePool.trees.Length; i++) { var tree = TreePool.trees [i]; if ((tree != null) && (!tree.activeSelf)) { return tree; } } return null; } }
LINQ を使ってみたかったのですが、Terrain のつなぎ目がおかしくなるので、やめました。^^;
(LINQの使いどころを勉強中です… ^^;;;
Planeの生成の変更点は、新たに”植林”が増えた処理です。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GenerateTerrain : MonoBehaviour { [SerializeField] int heightScale = 10; [SerializeField] float detailScale = 10.0f; //自分の所に植林した木 List<GameObject> myTrees = new List<GameObject>(); // Use this for initialization void Start () { var mesh = this.GetComponent<MeshFilter> ().mesh; var vertices = mesh.vertices; var pos = this.transform.position; for (int v = 0; v < vertices.Length; v++) { vertices [v].y = Mathf.PerlinNoise ( (vertices [v].x + pos.x) / this.detailScale, (vertices [v].z + pos.z) / this.detailScale) * this.heightScale; //Debug.Log (vertices [v].y); //植林 if ((vertices [v].y > 2.6f) && (Mathf.PerlinNoise((vertices[v].x+5)/10, (vertices[v].z+5)/10)*10 > 4.6f) && ((Random.Range(0, 1000) % 100) == 0) ) { var newTree = TreePool.getTree (); if (newTree != null) { var treePos = new Vector3 ( (vertices [v].x + this.transform.position.x), (vertices [v].y), (vertices [v].z + this.transform.position.z)); newTree.transform.position = treePos; newTree.SetActive (true); myTrees.Add (newTree); } } } mesh.vertices = vertices; mesh.RecalculateBounds (); mesh.RecalculateNormals (); this.gameObject.AddComponent<MeshCollider> (); } void OnDestroy() { //自分のところに植林した木を見えなくする for (int i = 0; i < this.myTrees.Count; i++) { var tree = this.myTrees [i]; if (tree != null) { tree.SetActive (false); } } this.myTrees.Clear (); } // Update is called once per frame void Update () { } }
Plane 生成時に プールからオブジェクトを参照して SetActive(true) にし、Plane破棄のときに、自分が植林した分を SetActive(false) にするポイントが、なるほどーと思いました。
わかっているようで、結局こういう実装をゼロからできていないので、やっぱり経験不足感を実感してます… ^^;;
木が浮いてしまう…のは、どうしたらいいかわからなかったですww ^^;
余談ですが…
動画のチュートリアルを試している時、MacBookAirではPlaneの生成するタイミングで処理が重くてカクカクする感じの原因が、まさか Debug.log だと思わず…無駄に実装を追求してましたが…勉強になりました。^^;
最後に、HTML5に出力してみました。
マウスで視点調整、方向キーで前後左右移動します。(マウスのカーソルをゲーム画面から外すには Escキー を押してください。)