numalog

ぬまおうの活動日誌

Unity tips #1 ObjectをInstantiate、カメラスクリプト、HPゲージバー、配列の仕様について

without comments

前ブログで書いていた、unity関連の記事で、検索エンジンなどの結果から需要がありそうなものを抜粋。

大量のObjectをInstantiateすると遅い

for loopなどで、Instantiateでオブジェクトを出す方法は簡単ではあるのですが、大量に生成するとかなりパフォーマンスが落ちます。
対策としては、それが静的なオブジェクトであれば、メッシュ頂点を編集して、1つのオブジェクトとしてまとめて生成する方法が早いです。

参考サイト

(英語)http://blog.nobel-joergensen.com/2010/12/25/procedural-generated-mesh-in-unity/

http://wise9.jp/archives/1479

サードパーソンカメラスクリプト

プレイヤーを追尾するカメラスクリプトのサンプルです。
unity4.x系で未確認。
また、今見るともうちょっとやりようあったなぁ というところが結構あるので、参考程度で。

なぜか変なpタグが入ってしまうので、お手数ですが使う際は取り除いてください。

using UnityEngine;
using System.Collections;
public class CameraMovement : MonoBehaviour {
    public GameObject targetObject;//追跡するゲームオブジェクト
    private Vector3 targetPosition;
    private Quaternion targetRotation;
    private Vector3 viewPoint;
    public Vector3 distanceVector;//カメラと追跡物の距離
    public Vector3 relativeViewPoint;//追跡物とカメラ視点の距離
    // Use this for initialization
    void Start () {
        Initialize();
    }</p>

<pre><code>// Update is called once per frame
void LateUpdate () {

    CaluculateViewPoint();
    CalculateCameraMovement();
    ApplyCameraMovement();

}

void Initialize(){
    targetPosition = new Vector3();
    targetRotation = new Quaternion();
    viewPoint = new Vector3();
}

void CalculateCameraMovement(){

    targetPosition = targetObject.transform.position + distanceVector;
    targetRotation = Quaternion.LookRotation( viewPoint – this.transform.position);

}

void CaluculateViewPoint(){
    viewPoint = targetObject.transform.position + relativeViewPoint;
}

void ApplyCameraMovement(){

    this.transform.position = targetPosition;
    this.transform.rotation = targetRotation;
}
</code></pre>

<p>}

WindowsServer2008でUnityを起動する

マイコンピューターを右クリック->プロパティ->システムの詳細設定->詳細設定タブ->パフォーマンスの”設定” ->データ実行防止タブ->次に選択するものを除く~->追加で”Unity.exe”を追加

ほかにも起動しないソフト、OSがあったら、この設定を試してみると動くようになるかも。

HPゲージバーの実装

サンプル

GUI.DrawTexture  (Rect (0,0, size.x, size.y),HudEmpty);</p>

<p>GUI.BeginGroup (Rect (0, 0,HPratio*size.x, size.y));
GUI.DrawTexture (Rect (0,0, size.x, size.y),HPMAX);
GUI.EndGroup ();

sizeはHPゲージの画像サイズx,yをVector2(x,y)として表現したもの HPratioは現在のHP/最大HPをFloat型で計算したもの 。 HudEmptyはゲージが空のときのテクスチャ、HPMAXはHPゲージが満タンのときのテクスチャ。

結局何をしているかというと、 GUI.BeginGroupのRectを、HPの比率(HPratio)により変形させることにより、 HPゲージのテクスチャの可視部分を変化させてゲージを表現しています。

UnityRPGでは、いまのところはこの方法をちょっと変形させたものを使っています。

ほかに考えられる方法としては、Groupじゃなくて単純にテクスチャのRectを引き伸ばしたりとかでしょうか。 ただテクスチャの変形だと、装飾が入っているゲージのときに、引き伸ばしにより表示が崩れてしまうので、 個人的にはBeginGroupによる方法が一番汎用的でいい気もします。

オブジェクト配列の初期化/Unityの配列の仕様

というか、オブジェクト指向言語について。 今昔の記事を見ると、分かってなさすぎてちょっと恥ずかしかったりするのですが、

var inventory:ItemIndex;
inventory = new ItemIndex[Size];
inventory[2].hogehoge();
の3行目は出来ませんよ。という話。
なぜかというと、newで宣言しているところではただ参照を格納する変数(ポインタ)を確保しているだけで、その先のobjectを生成していないから。
土地は確保したけれど、建物がマダですよ という感じ。
単一の new Hoge(foo)とちがって、コンストラクターを呼んでいないので、実態はありません

inventory = new ItemIndex[Size];
for (i = 0; i < Size; i++) {
  inventory[i] = new ItemIndex();
}
こうして、各要素の先にobjectを作ってあげる必要があります。

また、Javascript(C#も というか大抵のオブジェクト指向言語)には、

  • プリミティブな配列

var hoge = new int[50];みたいな形で宣言。
アクセスはhoge[3]とする。hoge[3].push()などのメソッドは基本的に一切持たない   割と高速

  • ArrayListクラス

var arr = new Array(); (javascript)
ArrayList arr = new ArrayList(); (C#)
みたいな形で宣言。 アクセスはarr[50]など、jsとC#ではプリミティブ配列と同じ形で可能。arr.push()、arr.pop()など、メソッドを持つ

という、2種類の配列があります。

一番の違いは、かなりざっくり言うと下のArrayListはクラスの一つ、だからメソッドがあり、余計な操作してくれるので動的な要領確保メソッドがある。
上は組み込み型(int、floatみたいなの)。だからメソッドがない。余計な操作がないので動的に要領確保できない。
厳密に言えば正確ではないのですが、大体このような認識をしておけばいいと思います。
もしどの配列を使えばいいか迷ったら、基本的には下のArrayListを使いましょう。
上はどうしても速度が出ないなど、理由がない限りは使わないでいいかと思います。
たとえばCからはじめたので、ArrayListに慣れていない という場合でもなるべく使用して使い方を覚えたほうがいいと思います。 慣れるとプリミティブよりはるかに読みやすくコードを記述できたり、配列をクラスオブジェクトとして扱うのは、他の言語でもよく使われる手法なので、かなり役立ちます。


Written by numa

5月 3rd, 2013 at 4:15 am

Posted in プログラミング

Tagged with

Leave a Reply