こんにちは。
unityで3Dのクレーンゲームを個人開発しようと思うのですが
どういった方法で動作させればいいのかわかりません。
とりあえず筐体を左右に移動はできました。が、
アームを開ける→筐体を下げる→アームを閉じる→筐体を上げる→初期位置まで戻りアームを開く
上記の動作をどういった方法で実現できますでしょうか。
初心者なのでわからないことだらけですが教えていただけると助かります。
C#で動かすべきなのでしょうか?
はたまたアニメーションで動かすべきなのでしょうか…?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
一案としましては、去年の話ですがC# - Unityでゲーム内の物理的負荷をトリガーにしたい|teratailのご質問に案を投稿した際には、一連の動きを表現するのに入れ子のコルーチンを使ってみました。
投稿したコードでは、ご要望を実現しようと試行錯誤した結果クローをアームにジョイントで繋いで開閉していますが、クローもKinematicにしてしまいMoveRotationで回転させる方が制御が簡単かもしれません。
#追記
水平位置を元に戻すには、Craneがアタッチされたオブジェクトを元の位置に戻してやればよさそうですね。
Craneスクリプトに水平移動モーションを追加してみました。元々のコメントは削除し、今回変更があった部分にのみコメントを加えています。
C#
1using System.Collections; 2using System.Linq; 3using UnityEngine; 4 5public class Crane : MonoBehaviour 6{ 7 public Transform armTransform; 8 public Joint LoadDetectorJoint; 9 public HingeJoint[] ClawHinges; 10 11 private bool playing; 12 private float homePositionY; // フィールド名をhomePositionYに変更 13 private Vector2 homePositionXZ; // 水平位置用のフィールドを追加 14 15 private void Start() 16 { 17 this.homePositionY = armTransform.position.y; // フィールド名をhomePositionYに変更 18 this.homePositionXZ = new Vector2(this.transform.position.x, this.transform.position.z); // アーム上昇後、水平位置をここへ移動する 19 } 20 21 private void Update() 22 { 23 if (!this.playing && Input.GetKeyDown(KeyCode.Space)) 24 { 25 this.StartCoroutine(this.StartGame()); 26 } 27 } 28 29 private IEnumerator StartGame() 30 { 31 this.playing = true; 32 33 Debug.Log("Start!"); 34 35 yield return this.StartCoroutine(this.MoveClawsMotion(60.0f)); 36 yield return new WaitForSeconds(1.0f); 37 yield return this.StartCoroutine(this.MoveDownMotion()); 38 yield return new WaitForSeconds(1.0f); 39 yield return this.StartCoroutine(this.MoveClawsMotion(0.0f)); 40 yield return new WaitForSeconds(1.0f); 41 yield return this.StartCoroutine(this.MoveUpMotion()); 42 yield return new WaitForSeconds(1.0f); 43 yield return this.StartCoroutine(this.ReturnHomeMotion()); // 水平位置を元に戻す 44 yield return new WaitForSeconds(1.0f); // 少し待機 45 yield return this.StartCoroutine(this.MoveClawsMotion(60.0f)); 46 yield return new WaitForSeconds(1.0f); 47 yield return this.StartCoroutine(this.MoveClawsMotion(0.0f)); 48 49 this.playing = false; 50 } 51 52 private IEnumerator MoveDownMotion() 53 { 54 const int loadMovingAverageLength = 30; 55 const float loadThreshold = 0.0f; 56 const float acceleration = 0.5f; 57 const float velocityMax = 1.0f; 58 59 var loads = Enumerable.Repeat<float>(this.LoadDetectorJoint.currentForce.y, loadMovingAverageLength).ToArray(); 60 var loadSum = loads.Sum(); 61 var loadIndex = 0; 62 63 var velocity = 0.0f; 64 65 while (true) 66 { 67 var previousLoad = loads[loadIndex]; 68 var newLoad = this.LoadDetectorJoint.currentForce.y; 69 70 loadSum += (newLoad - previousLoad); 71 72 var averageLoad = loadSum / loadMovingAverageLength; 73 74 Debug.LogFormat("Load:{0}", averageLoad); 75 76 if (averageLoad >= loadThreshold) 77 { 78 Debug.Log("Stop!"); 79 break; 80 } 81 82 velocity = Mathf.Max(velocity - acceleration * Time.deltaTime, -velocityMax); 83 this.armTransform.Translate(0.0f, velocity * Time.deltaTime, 0.0f, Space.World); 84 loadIndex = (loadIndex + 1) % loadMovingAverageLength; 85 86 yield return null; 87 } 88 } 89 90 private IEnumerator MoveUpMotion() 91 { 92 const float acceleration = 0.5f; 93 const float velocityMax = 1.0f; 94 95 var velocity = 0.0f; 96 97 while (this.armTransform.position.y < this.homePositionY) // フィールド名をhomePositionYに変更 98 { 99 velocity = Mathf.Min(velocity + acceleration * Time.deltaTime, velocityMax); 100 this.armTransform.Translate(0.0f, velocity * Time.deltaTime, 0.0f, Space.World); 101 102 yield return null; 103 } 104 105 // コメントで申し上げたように、アームのX、Zを0にしてしまわないように変更しました 106 var armPosition = this.armTransform.position; 107 armPosition.y = this.homePositionY; // フィールド名をhomePositionYに変更 108 this.armTransform.position = armPosition; 109 } 110 111 // 元の位置に戻すためのモーションを追加 112 // クレーンゲームらしくしようと思い、景品を持ち上げた位置から一直線に戻るのではなく、XとZを独立して動かしています 113 private IEnumerator ReturnHomeMotion() 114 { 115 const float acceleration = 0.5f; // X軸またはZ軸の移動加速度 116 const float velocityMax = 1.0f; // X軸またはZ軸の最大移動速度 117 118 var velocity = 0.0f; 119 var position = new Vector2(this.transform.position.x, this.transform.position.z); // 現在の水平位置 120 121 // ホームポジションへの向きの符号を求める...移動方向のコントロールに使う 122 var sign = this.homePositionXZ - position; 123 sign.x = Mathf.Sign(sign.x); 124 sign.y = Mathf.Sign(sign.y); 125 126 while (true) 127 { 128 // ホームポジションへの相対位置を求め、十分近づいたら移動を終える 129 var left = this.homePositionXZ - position; 130 if (Mathf.Approximately(left.sqrMagnitude, 0.0f)) 131 { 132 break; 133 } 134 135 velocity = Mathf.Min(velocity + acceleration * Time.deltaTime, velocityMax); 136 var delta = velocity * Time.deltaTime; // XまたはZ方向の、このフレームでの移動量 137 var nextPosition = position + sign * delta; // このフレームでの移動先 138 139 // 目標地点を越えないように座標をクランプしてから、そこへ移動 140 position.x = sign.x > 0.0f ? Mathf.Min(nextPosition.x, this.homePositionXZ.x) : Mathf.Max(nextPosition.x, this.homePositionXZ.x); 141 position.y = sign.y > 0.0f ? Mathf.Min(nextPosition.y, this.homePositionXZ.y) : Mathf.Max(nextPosition.y, this.homePositionXZ.y); 142 this.transform.position = new Vector3(position.x, this.homePositionY, position.y); 143 144 yield return null; 145 } 146 147 this.transform.position = new Vector3(this.homePositionXZ.x, this.homePositionY, this.homePositionXZ.y); 148 } 149 150 private IEnumerator MoveClawsMotion(float angle, float timeout = 3.0f) 151 { 152 const float angularSpeed = 30.0f; 153 154 var time = 0.0f; 155 156 while (time < timeout) 157 { 158 var reached = true; 159 var angleDeltaMax = angularSpeed * Time.deltaTime; 160 161 foreach (var clawHinge in this.ClawHinges) 162 { 163 var spring = clawHinge.spring; 164 165 spring.targetPosition = Mathf.MoveTowardsAngle(spring.targetPosition, angle, angleDeltaMax); 166 clawHinge.spring = spring; 167 reached &= Mathf.Approximately(spring.targetPosition, angle); 168 } 169 170 if (reached) 171 { 172 break; 173 } 174 175 time += Time.deltaTime; 176 177 yield return null; 178 } 179 } 180}
投稿2018/11/11 21:59
編集2018/11/17 00:38総合スコア10811
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/11/12 07:37
2018/11/12 10:25
2018/11/12 14:10 編集
2018/11/13 00:43 編集
2018/11/13 09:32
2018/11/13 20:16
2018/11/14 15:05
2018/11/14 21:43
2018/11/15 08:32
2018/11/15 08:34
2018/11/15 20:01
2018/11/16 09:33
2018/11/17 00:40
2018/11/17 02:06