【趣味】【ゲーム開発】2DQVの細長い建物にも3DSLを適応するスクリプト
前回の記事で作ったスクリプトの仕様の
予期できる問題の修正スクリプトを
公開することにしました。
建物が細長いと、このような不具合が生じます。
その修正版に更新しました。
まずは前回の記事のスクリプトの更新版です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
using UnityEngine; public class ZPositionToggler : MonoBehaviour { [Header("境界線")] [SerializeField, Tooltip("境界線設定用の親Transform")] protected Transform borderParent = default; [SerializeField, Tooltip("Y軸の境界線")] protected float yBorder = 0.0f; [SerializeField, Tooltip("X軸境界線(Y軸境界線より左側の時)")] protected float leftXBorder = 0.0f; [SerializeField, Tooltip("X軸境界線(Y軸境界線より右側の時)")] protected float rightXBorder = 0.0f; [Header("対象のZ座標設定")] [SerializeField, Tooltip("対象のTransform(スポットライトの原点など)")] protected Transform targetTransform = default; [SerializeField, Tooltip("Z座標設定(X軸境界線よりも上に対象がある時)")] protected float zPosWhenOverXBorder = 0.1f; [SerializeField, Tooltip("Z座標設定(X軸境界線よりも下に対象がある時)")] protected float zPosWhenUnderXBorder = -0.1f; [Header("デバッグ表示用")] [SerializeField, Tooltip("X軸境界線の長さ")] protected float xLineLength = 32.0f; [SerializeField, Tooltip("Y軸境界線の長さ")] protected float yLineLength = 32.0f; /// <summary> /// ターゲットY座標と比較して比較X軸境界線を取得する /// </summary> protected virtual float? GetXBorderPos(Vector3 targetPos) { float yBorderPos = borderParent.position.x + yBorder; return borderParent.position.x + ((targetPos.x > yBorderPos) ? rightXBorder : leftXBorder); } /// <summary> /// ターゲット座標と比較してZ座標を取得する /// </summary> protected virtual float? GetZPos(Vector3 targetPos) { float? xBorderPos = GetXBorderPos(targetPos); if (!xBorderPos.HasValue) { return null; } return ((targetPos.y > xBorderPos.Value) ? zPosWhenOverXBorder : zPosWhenUnderXBorder); } /// <summary> /// Unity更新時処理 /// </summary> protected virtual void FixedUpdate() { // 対象のTransformが未設定のため、早期リターン if (targetTransform == null) { Debug.LogError("対象のTransformが未設定です"); return; } // 境界線の親Transformが未設定のため、早期リターン if (borderParent == null) { Debug.LogError("境界線の親Transformが未設定です"); return; } // Z座標更新 float? zPos = GetZPos(targetTransform.position); if (zPos.HasValue) { Vector3 temp = transform.position; temp.z = zPos.Value; transform.position = temp; } } /// <summary> /// ギズモ(デバッグ用の線)を描画する /// </summary> protected virtual void OnDrawGizmosSelected() { // Unityエディタ起動時のみ表示する #if UNITY_EDITOR // 境界線の親Transformが設定されていないなら、 // ギズモ描画不可能なので早期リターン if (borderParent == null) { Debug.LogError("境界線の親Transformが未設定です"); return; } // 計算用変数 Vector3 tempFrom; Vector3 tempTo; // Y軸境界線描画 Vector3 yBorderPos = borderParent.position; yBorderPos.x += yBorder; Gizmos.color = Color.green; tempFrom = yBorderPos; tempFrom.y += yLineLength * 0.5f; tempTo = yBorderPos; tempTo.y -= yLineLength * 0.5f; Gizmos.DrawLine(tempFrom, tempTo); // X軸境界線(左)描画 Gizmos.color = Color.red; tempFrom = yBorderPos; tempFrom.y += leftXBorder; tempTo = tempFrom; tempTo.x -= xLineLength; Gizmos.DrawLine(tempFrom, tempTo); // X軸境界線(右)描画 tempFrom = yBorderPos; tempFrom.y += rightXBorder; tempTo = tempFrom; tempTo.x += xLineLength; Gizmos.DrawLine(tempFrom, tempTo); #endif } } |
継承を可能にしたことと、
処理を中断するためのnull許容と
nullチェック処理を実装しています。
そしてこちらが拡張実装です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
using UnityEngine; public class ZPositionTogglerSlender : ZPositionToggler { [Header("境界線(細長建物用)")] [SerializeField, Tooltip("Y軸境界線の幅(この幅の間ではZ軸座標切り替えを行わない)")] protected float yBorderWidth = 0.0f; /// <summary> /// ターゲットY座標と比較して比較X軸境界線を取得する /// </summary> protected override float? GetXBorderPos(Vector3 targetPos) { float yBorderCenterPos = borderParent.position.x + yBorder; float yBorderWidthHalf = Mathf.Abs(yBorderWidth) * 0.5f; if (targetPos.x < yBorderCenterPos - yBorderWidthHalf) { return borderParent.position.x + leftXBorder; } if (targetPos.x > yBorderCenterPos + yBorderWidthHalf) { return borderParent.position.y + rightXBorder; } return null; } /// <summary> /// ギズモ(デバッグ用の線)を描画する /// </summary> protected override void OnDrawGizmosSelected() { // Unityエディタ起動時のみ表示する #if UNITY_EDITOR // 境界線の親Transformが設定されていないなら、 // ギズモ描画不可能なので早期リターン if (borderParent == null) { Debug.LogError("境界線の親Transformが未設定です"); return; } // 計算用変数 Vector3 tempFrom; Vector3 tempTo; // Y軸境界線描画 Vector3 yBorderCenterPos = borderParent.position; yBorderCenterPos.x += yBorder; float yBorderWidthAbs = Mathf.Abs(yBorderWidth); Gizmos.color = Color.green; tempFrom = yBorderCenterPos; tempFrom.x -= yBorderWidthAbs * 0.5f; tempFrom.y += yLineLength * 0.5f; tempTo = yBorderCenterPos; tempTo.x -= yBorderWidthAbs * 0.5f; tempTo.y -= yLineLength * 0.5f; Gizmos.DrawLine(tempFrom, tempTo); tempFrom.x += yBorderWidthAbs; tempTo.x += yBorderWidthAbs; Gizmos.DrawLine(tempFrom, tempTo); // X軸境界線(左)描画 Gizmos.color = Color.red; tempFrom = yBorderCenterPos; tempFrom.x -= yBorderWidthAbs * 0.5f; tempFrom.y += leftXBorder; tempTo = tempFrom; tempTo.x -= xLineLength; Gizmos.DrawLine(tempFrom, tempTo); // X軸境界線(右)描画 tempFrom = yBorderCenterPos; tempFrom.x += yBorderWidthAbs * 0.5f; tempFrom.y += rightXBorder; tempTo = tempFrom; tempTo.x += xLineLength; Gizmos.DrawLine(tempFrom, tempTo); #endif } } |
この手のスクリプト更新を得られやすいように、
GitHub使うべきかなぁ。
ちなみに、OnTriggerStay2D()とか使うほうが
Unityらしいし、コーディングもスマートになるし、
処理効率的にもいいんだろうなとは思うんですけど、
正直、Trigger使う実装ってめんどくさいなって思います。
トリガーを受ける側はもちろんですけど、
トリガーに当たる側のにもトリガー作る必要があるし、
トリガーのレイヤー分けとかもあるんで…。
あと個人的にはOdinInspectorに準拠した
設計にしたいなとか思うんですけど、
あれ、高いから使ってない人多いよね。