Unityでストップウォッチを作る その2 メッシュとテクスチャの作成


前回はタイム表示をしたので、次は目盛りのラインなどを描画したいと思う訳ですが、Unityで描画をするにはまずなによりメッシュが必要になります。しかし、Unityのプロジェクトを作った段階では、CubeやらSphereなどの3D用のものが数種類と、無駄に細かいメッシュのPlaneしか作れません。BigStopWatchのラインひとつひとつを標準のPlaneで置いていくのはちょっと無駄な感じです。

さらにBigStopWatchではきれいなラインを引くために、テクスチャにラインを描画して少しマージンを付けたものをメッシュに割り当てて描画しています。メッシュを単純に塗りつぶすとメッシュのエッジ部分がガタガタになってしまいます。なのでそのテクスチャも作りたいのですが、Unityのメニューのどこを見渡してもテクスチャを作成するような項目は見つかりません。

しかし、なければ自分で作ってしまえるというのもUnityの良い所です。今回はエディタ拡張をちょっとだけ使ってメッシュとテクスチャを作れるようにしたいと思います。

メッシュとテクスチャをスクリプトで作る

Projectウィンドウ内のメニューから「Create/Folder」を選択して「Editor」というフォルダを作成します。このフォルダ名は重要です。以後作っていくフォルダ名は適当で良いですが、これはちゃんと「Editor」としてください。

その「Editor」フォルダ内に
「BSWEditorUtility.cs」
「CreateEmptyMesh.cs」
「CreateTexture.cs」
という3つのC#スクリプトを作成してください。

unitysw_2_1.png

それぞれのスクリプトは以下になります。

//
// BSWEditorUtility
//
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections;
public class BSWEditorUtility : MonoBehaviour {
  static public string GetSelectedDirectoryPath() {
     
    string path = null;
     
    foreach (UnityEngine.Object obj in Selection.objects) {
         
      path = AssetDatabase.GetAssetPath(obj);
         
      if (!string.IsNullOrEmpty(path) && !Directory.Exists(path)) {
        path = Path.GetDirectoryName(path);
      }
         
      break;
    }
     
    if (string.IsNullOrEmpty(path)) {
     return "Assets";
    }
     
    return path;
  }
}
//
// CreateTexture.cs
//
using UnityEngine;
using UnityEditor;
using System.Collections;
public class CreateTexture : ScriptableWizard {
 
  public string textureName;
  public int width = 256;
  public int height = 256;
  public TextureFormat textureFormat = TextureFormat.ARGB32;
  
  [MenuItem ("Assets/Create/Texture...")]
  static void CreateWizard()
  {
    ScriptableWizard.DisplayWizard("Create Texture", typeof(CreateTexture));
  }
  
  void OnWizardCreate() {
    
    if (string.IsNullOrEmpty(textureName)) {
      textureName = "New Texture " + width + "x" + height;
    }
     
    string path = BSWEditorUtility.GetSelectedDirectoryPath() + "/" + textureName + ".asset";
    path = AssetDatabase.GenerateUniqueAssetPath(path);
    
    Texture2D tex = new Texture2D(width, height, textureFormat, false);
    tex.name = textureName;
     
    ClearTexture(tex);
    
    AssetDatabase.CreateAsset(tex, path);
  }
   
  static public void ClearTexture(Texture2D tex) {
     
    int texWidth = tex.width;
    int texHeight = tex.height;
     
    for (int x = 0; x < texWidth; x++) {
      for (int y = 0; y < texHeight; y++) {
        tex.SetPixel(x, y, Color.clear);
      }
    }
  }
}
//
// CreateEmptyMesh.cs
//
using UnityEngine;
using UnityEditor;
using System.Collections;
public class CreateEmptyMesh : MonoBehaviour {
  [MenuItem ("Assets/Create/Empty Mesh")]
  static void Create() {
   
    string path = BSWEditorUtility.GetSelectedDirectoryPath() + "/New Empty Mesh.asset";
    path = AssetDatabase.GenerateUniqueAssetPath(path);
   
    Mesh mesh = new Mesh();
   
    AssetDatabase.CreateAsset(mesh, path);
  }
}

これらのコードを追加する事でメニューの「Assets/Create/」の中に新たにメニュー項目が追加されます。「Empty Mesh」を選択すれば空のメッシュが作成でき、「Texture...」を選択すればサイズを指定してテクスチャが作成できるようになります。

ちょっと解説

今回のスクリプトには全て「using UnityEditor」という宣言が追加されています。この名前空間にはエディタとしての機能を利用できるクラス、例えば今回だとAssetDatabaseというプロジェクトウィンドウ内のアセットにアクセスできるクラスなどがあります。UnityEditorの名前空間を使うスクリプトは「Editor」フォルダに入れておかないといけないようです。と言っても、エディター上で実行しているだけなら「Editor」フォルダに入れていなくても問題なく使えてしまいます。ただ、ビルドするときにはエラーが出てしまうので、何かの理由でEditorフォルダに入れたくないということがあるようでしたら、以下のページに解決法が書いてありましたので、参考にすると良いと思います。
【Unity Tips】using UnityEditorを使うけどEditorに入れたくない

メニューに項目を追加して実行できるようにしているのは「[MenuItem ("〜")]」という一行です。これによってメニューに項目が追加され、このあとに記述されたメソッドがメニューを選択すると実行されます。ちなみに、「Asset/Create/」というメニューのパスで指定されたものは、画面上のメニューのAssetsに表示されるだけでなく、ProjectウィンドウのCreateメニューにも表示されます。

unitysw_2_3.png

「BSWEditorUtility」はメッシュとテクスチャの両方共通の処理があったので作りました。GetSelectedDirectoryPath()というのがそれで、Projectウィンドウで選択されているフォルダを取得するものです。Selectionクラスで選択されているフォルダorファイルが取得できるので、選択されていればその階層のフォルダを返し、選択されていない場合は最上位階層の「Assets」を返すようにしています。

「CreateEmptyMesh」と「CreateTexture」は、それぞれ新たにメッシュやテクスチャを作成してアセットとして保存するということをやっています。ただ単に「new Mesh()」とするだけではいずれどこかに消えてなくなりますが、AssetDatabase.CreateAsset()でアセットとして保存して残せます。

今回は以上です。次回は実際にメッシュの中身を作成します。

前へ | 次へ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です