📗
【Unity】型の拡張メソッドについて
はじめに
初めての方も、そうでない方もこんにちは!
現役ゲームプログラマーのたむぼーです。
自己紹介を載せているので、気になる方は見ていただければ嬉しいです!
今回は
型の拡張メソッド
について紹介します
拡張メソッドとは
第一引数にthis 対象の型 変数名を入れた関数を作ることで、以下のように呼び出せる関数です
例
static public class StringEx
{
/// <summary>
/// ログを表示
/// </summary>
static public void Log(this string message)
{
Debug.LogError("Log : " + message);
}
}
public class Example
{
private string _message;
public void Example1()
{
_message = "これはExample1です!";
_message.Log(); // StringExのLogを呼び出す
}
}
実行結果
Log : これはExample1です!
いろいろな型の拡張メソッド
GameObjectEx
GameObjectEx.cs
using UnityEngine;
namespace ProjectName.Ex
{
static public class GameObjectEx
{
/// <summary>
/// コンポーネント取得/追加
/// </summary>
static public T GetOrAddComponent<T>(this GameObject self) where T : Component
{
if (self.TryGetComponent<T>(out T component))
{
return component;
}
return self.AddComponent<T>();
}
/// <summary>
/// アクティブ状態の設定
/// </summary>
static public void SetActiveSafe(this GameObject self, bool isActive)
{
if (self == null)
{
return;
}
if (self.activeSelf != isActive)
{
self.SetActive(isActive);
}
}
}
}
ComponentEx
ComponentEx.cs
using UnityEngine;
namespace ProjectName.Ex
{
static public class ComponentEx
{
/// <summary>
/// コンポーネント取得/追加
/// </summary>
static public T GetOrAddComponent<T>(this Component self) where T : Component
{
if (self.gameObject.TryGetComponent<T>(out T component))
{
return component;
}
return self.gameObject.AddComponent<T>();
}
/// <summary>
/// アクティブ状態の設定
/// </summary>
static public void SetActiveSafe(this Component self, bool isActive)
{
if (self == null)
{
return;
}
self.gameObject.SetActiveSafe(isActive);
}
/// <summary>
/// ルートのキャンバスを取得
/// </summary>
static public Canvas FindRootCanvas(this Component self)
{
return self.transform.root.GetComponentInChildren<Canvas>();
}
}
}
DictionaryEx
DictionaryEx.cs
using System.Collections.Generic;
namespace ProjectName.Ex
{
static public class DictionaryEx
{
/// <summary>
/// 安全な獲得
/// </summary>
static public V GetValueSafe<K, V>(this Dictionary<K, V> self, K key)
{
if (self.TryGetValue(key, out V value))
{
return value;
}
return default;
}
/// <summary>
/// 安全な追加
/// </summary>
static public void AddValueSafe<K, V>(this Dictionary<K, V> self, K key, V value)
{
if (self.ContainsKey(key))
{
self[key] = value;
}
else
{
self.Add(key, value);
}
}
}
}
ListEx
ListEx.cs
using System.Collections.Generic;
namespace ProjectName.Ex
{
static public class ListEx
{
/// <summary>
/// 安全な追加
/// </summary>
static public void AddSafe<T>(this List<T> self, T data) where T : class
{
if (data == null)
{
return;
}
self?.Add(data);
}
/// <summary>
/// 安全な獲得
/// </summary>
static public V GetValueSafe<V>(this List<V> self, int id)
{
if (self == null || id < 0 || self.Count <= id)
{
return default(V);
}
return self[id];
}
}
}
ObjectEx
ObjectEx.cs
using UnityEngine;
namespace ProjectName.Ex
{
static public class ObjectEx
{
/// <summary>
/// 安全にキャスト
/// </summary>
static public bool SafeCast<T>(this object obj, out T result)
{
if (obj is T castedValue)
{
result = castedValue;
return true;
}
else
{
Debug.LogError($"Failed to cast {obj} to {typeof(T)}");
result = default;
return false;
}
}
}
}
StringEx
StringEx.cs
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System;
namespace ProjectName.Ex
{
static public class StringEx
{
/// <summary>
/// 指定されたフォーマットで文字列を置換
/// </summary>
static public string ReplaceFormat(this string str, Dictionary<string, string> param)
{
StringBuilder builder = UseBuilder();
builder.Append(str);
foreach (var val in param)
{
builder.Replace(val.Key, val.Value);
}
return Flash(builder);
}
/// <summary>
/// 指定されたフォーマットで文字列を追加
/// </summary>
static public string AppendFormat(this string format, string str)
{
StringBuilder builder = UseBuilder();
if (string.IsNullOrEmpty(format))
{
return str;
}
builder.AppendFormat(format, str);
return Flash(builder);
}
/// <summary>
/// 指定されたフォーマットで2つの文字列を追加
/// </summary>
static public string AppendFormat(this string format, string str, string str2)
{
StringBuilder builder = UseBuilder();
builder.AppendFormat(format, str, str2);
return Flash(builder);
}
/// <summary>
/// 指定されたフォーマットで整数を追加
/// </summary>
static public string AppendFormat(this string format, int str)
{
StringBuilder builder = UseBuilder();
builder.AppendFormat(format, str);
return Flash(builder);
}
/// <summary>
/// 指定されたフォーマットで2つの整数を追加
/// </summary>
static public string AppendFormat(this string format, int str, int str2)
{
StringBuilder builder = UseBuilder();
builder.AppendFormat(format, str, str2);
return Flash(builder);
}
/// <summary>
/// 指定されたフォーマットで可変長引数を追加
/// </summary>
static public string AppendFormat(this string format, params object[] p)
{
StringBuilder builder = UseBuilder();
builder.AppendFormat(format, p);
return Flash(builder);
}
/// <summary>
/// 文字列を結合
/// </summary>
static public string Join(this string self, string join)
{
StringBuilder builder = UseBuilder();
builder.Append(self);
builder.Append(join);
return Flash(builder);
}
/// <summary>
/// パス文字列を結合
/// </summary>
static public string JoinPath(this string self, string join)
{
self = self.Replace("\\", "/").Trim();
StringBuilder builder = UseBuilder();
builder.Append(self);
if (!self.EndsWith("/"))
{
builder.Append("/");
}
builder.Append(join);
return Flash(builder);
}
#if UNITY_EDITOR
/// <summary>
/// Assetsフォルダ内のパスを作成
/// </summary>
static public string MakeAssetsPath(this string self)
{
return UnityEngine.Application.dataPath.JoinPath(self.Replace("\\", "/").Replace("Assets", ""));
}
#endif
/// <summary>
/// 文字列リストを結合
/// </summary>
static public string Combine(this List<string> self)
{
return Combine(self, Environment.NewLine);
}
/// <summary>
/// 指定された区切り文字で文字列リストを結合
/// </summary>
static public string Combine(this List<string> self, string separator)
{
if (self == null || self.Count <= 0)
{
return "";
}
StringBuilder builder = UseBuilder();
for (int i = 0; i < self.Count; i++)
{
if (0 < i)
builder.Append(separator);
builder.Append(self[i]);
}
return builder.ToString();
}
/// <summary>
/// 改行の設定
/// </summary>
static public string ReplaceNewLine(this string str)
{
return ReplaceNewLine(str, Environment.NewLine);
}
/// <summary>
/// 改行の削除
/// </summary>
static public string OmitNewLine(this string str)
{
return ReplaceNewLine(str, "");
}
/// <summary>
/// 改行の設定
/// </summary>
static public string ReplaceNewLine(this string str, string ch)
{
var builder = UseBuilder();
builder.Append(str);
builder.Replace("\n\r", "[NR]");
builder.Replace("\r\n", "[NR]");
builder.Replace("\r", "[NR]");
builder.Replace("\n", "[NR]");
builder.Replace("[NR]", ch);
return Flash(builder);
}
/// <summary>
/// 数値のFormat指定での文字列化
/// </summary>
static public string ToStringFormat(this int val, string format)
{
var builder = UseBuilder();
builder.AppendFormat(format, val);
return Flash(builder);
}
/// <summary>
/// 数値のFormat指定での文字列化
/// </summary>
static public string ToStringFormat(this float val, string format)
{
var builder = UseBuilder();
builder.AppendFormat(format, val);
return Flash(builder);
}
/// <summary>
/// Int化
/// </summary>
static public int ToInt(this string self)
{
if (int.TryParse(self, out int result))
{
return result;
}
return 0;
}
/// <summary>
/// Long化
/// </summary>
static public long ToLong(this string self)
{
if (long.TryParse(self, out long result))
{
return result;
}
return 0;
}
/// <summary>
/// Double化
/// </summary>
static public double ToDouble(this string self)
{
if (double.TryParse(self, out double result))
{
return result;
}
return 0d;
}
/// <summary>
/// Float化
/// </summary>
static public float ToFloat(this string self)
{
if (float.TryParse(self, out float result))
{
return result;
}
return 0.0f;
}
/// <summary>
/// Bool化
/// </summary>
static public bool ToBool(this string self)
{
if (bool.TryParse(self, out bool result))
{
return result;
}
return false;
}
/// <summary>
/// Enum化
/// </summary>
static public T ToEnum<T>(this string self) where T : struct
{
if (Enum.TryParse(self, out T result) && Enum.IsDefined(typeof(T), result))
{
return result;
}
throw new ArgumentException($"Invalid Enum value for type {typeof(T)}: {self}");
}
/// <summary>
/// Enum化
/// </summary>
static public object ToEnum(this string self, Type type)
{
if (Enum.IsDefined(type, self))
{
return Enum.Parse(type, self);
}
throw new ArgumentException($"Invalid Enum value for type {type}: {self}");
}
/// <summary>
/// 行数カウンター
/// </summary>
static public int LineCount(this string self)
{
return self.Count(c => c == '\n') + 1;
}
/// <summary>
/// 文字列の末尾が一致するか
/// </summary>
static public bool EndsWithEx(this string a, string b)
{
if (a == null || b == null || a.Length < b.Length)
{
return false;
}
return a.Substring(a.Length - b.Length) == b;
}
private static List<StringBuilder> _builderPool = new List<StringBuilder>();
private const int MaxPoolSize = 10;
/// <summary>
/// ビルダーの取得
/// </summary>
static public StringBuilder UseBuilder()
{
StringBuilder builder = null;
lock (_builderPool)
{
if (_builderPool.Count > 0)
{
builder = _builderPool[_builderPool.Count - 1];
_builderPool.RemoveAt(_builderPool.Count - 1);
}
}
return builder ?? new StringBuilder();
}
/// <summary>
/// ビルダーの返却と文字列の取り出し
/// </summary>
static public string Flash(StringBuilder builder)
{
var str = builder.ToString();
lock (_builderPool)
{
if (_builderPool.Count < MaxPoolSize)
{
_builderPool.Add(builder);
}
builder.Length = 0;
}
return str;
}
}
}
Discussion