🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

1622閲覧

指定した場所に存在するオブジェクトを取得する

actionstudio

総合スコア39

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2021/01/10 12:38

#どのようなものを作っているか
今、unityの3Dでカップシャッフルゲームを作っています。
カップが三つありそれをシャッフルするのですが、ランダムにシャッフルするのでランダムに設定した変数によって移動させます。

#実現したいこと
その時、右端と左端にあるカップの位置を交換する場合、その場所にあるオブジェクトを移動させるオブジェクトとして取得してから、移動させたいです。なぜならば、数回移動させたのちに正解のしるしを入れたカップを取得したいからです。

カップはそれぞれ1,2,3と分けて区別してあります。

#試したこと
これまでには、オブジェクトをランダムに移動させるとき、移動させたのちに元居た位置に初期化し、それを移動させたと錯覚させて処理してきました。しかし、それだと正解のしるしを入れたカップを取得することができません。初期化してしまうために、正解のカップがどこに行ったのかわからなくなってしまうからです。

#####最後に
ネットで調べてみたのですが、自分のようなことをしている人が見つからず、解決することができませんでした。
指定した場所に存在するオブジェクトを取得するやり方でなくても構わないので、どのような処理にすれば目的が達成できるか教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

カップオブジェクトは現状の「実際に移動させたかのように錯覚させる」という方式のままにしておき、正解のカップがどれであるかはスクリプト上で別途追跡するというのはどうでしょう?
初期状態での正解カップ番号を変数に保持しておき、カップの交換が発生するたびに

  • 交換対象の番号がいずれも現在の正解カップ番号と異なる場合は、正解カップ番号を変更しない...たとえば現在の正解カップ番号が2の状態で、カップ1とカップ3の交換が行われた時には、正解カップ番号は2のまま維持する。
  • 交換対象の番号のいずれかが現在の正解カップ番号と一致する場合は正解カップ番号も入れ替える...たとえば現在の正解カップ番号が2の状態で、カップ1とカップ2の交換が行われた時には、正解カップ番号は1に変更する。現在の正解カップ番号が1の状態で、カップ1とカップ3の交換が行われた時には、正解カップ番号は3に変更する。

というルールで正解カップ番号を入れ替えていけば、シャッフルが終わった時点で何番目のカップが正解であるか分かるのではないでしょうか。

##追記

何かご参考になれば...と思いまして、下図のような実験シーンを作ってみました。

図1

3つのカップは空のオブジェクトの子オブジェクトとしてカップのモデルと景品のモデルを配置したものです。今回の実験ではカップ内に最初から景品を仕込んでおき、ハズレのカップは景品を非表示にすることで当たりのカップだけに景品が入っているように見せることにしました。
また、カップの動きを画面上で確認しやすくするため、各カップにはそれぞれ別々の色を付けました。実際のゲームだと、カップの見た目が違うと当たりカップを簡単に見破られてしまってまずいでしょうね。
これに下記のようなカップを開閉して景品を見せる動きをさせるためのスクリプトをアタッチしています。

C#

1using System.Collections; 2using UnityEngine; 3 4public class Mug : MonoBehaviour 5{ 6 [SerializeField] private float openHeight = 2.0f; 7 [SerializeField] private float animationLength = 1.0f; 8 9 private Coroutine currentAnimation; 10 private bool hasPrize; 11 private Transform mugModel; 12 private Transform prize; 13 14 public bool HasPrize 15 { 16 get => this.hasPrize; 17 set 18 { 19 this.prize.gameObject.SetActive(value); 20 this.hasPrize = value; 21 } 22 } 23 24 private void Awake() 25 { 26 this.mugModel = this.transform.Find("MugModel"); 27 this.prize = this.transform.Find("Prize"); 28 } 29 30 public void Open() 31 { 32 if (this.currentAnimation != null) 33 { 34 this.StopCoroutine(this.currentAnimation); 35 } 36 37 this.currentAnimation = this.StartCoroutine(this.DoAnimation(this.openHeight)); 38 } 39 40 public void Close() 41 { 42 if (this.currentAnimation != null) 43 { 44 this.StopCoroutine(this.currentAnimation); 45 } 46 47 this.currentAnimation = this.StartCoroutine(this.DoAnimation(0.0f)); 48 } 49 50 private IEnumerator DoAnimation(float destinationHeight) 51 { 52 var initialHeight = this.mugModel.localPosition.y; 53 for (var time = 0.0f; time < this.animationLength; time += Time.deltaTime) 54 { 55 var t = time / this.animationLength; 56 this.mugModel.localPosition = new Vector3( 57 0.0f, 58 Mathf.SmoothStep(initialHeight, destinationHeight, t), 59 0.0f); 60 yield return null; 61 } 62 63 this.mugModel.localPosition = new Vector3(0.0f, destinationHeight, 0.0f); 64 this.currentAnimation = null; 65 } 66}

Operatorがカップのシャッフル役で、下記のようなスクリプトをアタッチしました。インスペクター上でmugsにシーン上の3つのカップをセットしています。

C#

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using System.Linq; 5using UnityEngine; 6using Random = UnityEngine.Random; 7 8public class Operator : MonoBehaviour 9{ 10 [SerializeField] private float animationLength = 1.0f; 11 [SerializeField] private Mug[] mugs; 12 13 private int bingoIndex; 14 15 private IEnumerator Start() 16 { 17 // まずランダムな当たり番号を決め、その番号のカップに景品を仕込む 18 this.bingoIndex = Random.Range(0, this.mugs.Length); 19 for (var i = 0; i < this.mugs.Length; i++) 20 { 21 this.mugs[i].HasPrize = i == this.bingoIndex; 22 } 23 24 // ここで確認のためにコンソールに当たり番号を出力してみる 25 Debug.Log($"Bingo index: {this.bingoIndex}"); 26 27 yield return new WaitForSeconds(4.0f); 28 29 // カップを全部開き、中身を見せてみる 30 foreach (var mug in this.mugs) 31 { 32 mug.Open(); 33 yield return new WaitForSeconds(0.5f); 34 } 35 yield return new WaitForSeconds(2.0f); 36 37 // カップを全部閉じ... 38 foreach (var mug in this.mugs) 39 { 40 mug.Close(); 41 yield return new WaitForSeconds(0.5f); 42 } 43 yield return new WaitForSeconds(2.0f); 44 45 // ランダムに選んだ2つの番号を入れ替える操作を10回行う 46 var randomIndices = new List<int>(); 47 for (var i = 0; i < 10; i++) 48 { 49 randomIndices.Clear(); 50 randomIndices.AddRange( 51 Enumerable.Range(0, this.mugs.Length) 52 .Select(i => (i, guid: Guid.NewGuid())) 53 .OrderBy(p => p.guid) 54 .Select(p => p.i).Take(2)); 55 yield return this.Swap(randomIndices[0], randomIndices[1]); 56 57 // 1回交換するたびにコンソールに当たり番号を出力してみる 58 Debug.Log($"Bingo index: {this.bingoIndex}"); 59 } 60 yield return new WaitForSeconds(2.0f); 61 62 // カップを全部開き、中身を見せてみる 63 foreach (var mug in this.mugs) 64 { 65 mug.Open(); 66 yield return new WaitForSeconds(0.5f); 67 } 68 } 69 70 private IEnumerator Swap(int indexA, int indexB) 71 { 72 // 2つのカップが半円を描くようにアニメーションさせ... 73 var mugA = this.mugs[indexA]; 74 var mugB = this.mugs[indexB]; 75 var transformA = mugA.transform; 76 var transformB = mugB.transform; 77 var positionA = transformA.position; 78 var positionB = transformB.position; 79 var center = (positionA + positionB) * 0.5f; 80 var vectorA = positionA - center; 81 var vectorB = positionB - center; 82 for (var time = 0.0f; time < this.animationLength; time += Time.deltaTime) 83 { 84 var t = time / this.animationLength; 85 var r = Quaternion.Euler(0.0f, Mathf.SmoothStep(0.0f, 180.0f, t), 0.0f); 86 transformA.position = center + (r * vectorA); 87 transformB.position = center + (r * vectorB); 88 yield return null; 89 } 90 transformA.position = center + vectorB; 91 transformB.position = center + vectorA; 92 93 // mugs配列上の2つのカップを入れ替え... 94 this.mugs[indexA] = mugB; 95 this.mugs[indexB] = mugA; 96 97 // 必要に応じ当たり番号を更新する 98 if (this.bingoIndex == indexA) 99 { 100 this.bingoIndex = indexB; 101 } 102 else if (this.bingoIndex == indexB) 103 { 104 this.bingoIndex = indexA; 105 } 106 } 107}

動かしてみると、カップ入れ替え操作によってmugs配列の順序が変化していき、併せてbingoIndexの値も変化していきました。

図2

投稿2021/01/10 15:41

編集2021/01/11 14:57
Bongo

総合スコア10811

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

actionstudio

2021/01/10 23:46

回答ありがとうございます。挑戦してみます。 初期位置に戻すとなるとカップの向きが不自然になってしまったり、教えていただいたやり方だとコードが複雑になったり不便な点があるので、なるべく初期位置に戻すやり方は避けたいのですが もし何か思いついたら教えていただきたいです。
Bongo

2021/01/11 14:58

「別途当たり番号を追跡する」と申し上げた件については、さほど複雑な点はないかと思います。 ちょっと実験シーンを作ってみましたが、当たり番号更新ロジックはOperatorの... // 必要に応じ当たり番号を更新する if (this.bingoIndex == indexA) { this.bingoIndex = indexB; } else if (this.bingoIndex == indexB) { this.bingoIndex = indexA; } の部分で、当初の回答で申し上げた「交換を行ったとき、交換対象のカップのいずれかが当たりカップなら当たり番号も入れ替える」というのをそのまま実装した形です。ご参考になりますでしょうか?
actionstudio

2021/01/12 03:29

とても丁寧に教えて下さりありがとうございます。その処理が複雑でないのは理解できました。しかし、追記の部分が難しくてどうしても理解できそうにありません。初めて数週間しかたってなくまだ基礎知識がしっかりできてないので、これから地道に調べながらやっていこうと思っています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問