前回の続き。
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キー を押してください。)
