シーンに配置した目印のオブジェクトから、指定の数だけランダムに選んでアイテムと置き換えます。
まずアイテムの赤い球と、目印に使う小さなシリンダーのプレハブを用意しました。
空のゲームオブジェクトを作って、その子オブジェクトとしてシリンダーを一つヒエラルキーウィンドウにドラッグアンドドロップします。そして、そのシリンダーを選択したまま、作りたい目印の数だけCtrl + Dを押してこれを複製します。
複製されたシリンダーをシーンビューで地面に配置していきます。 シリンダーを選択して移動ツールを有効にしているときに、ShiftキーとCtrlキーを同時に押している間は、ギズモの中心に黄色い四角形が表示されます。これをドラッグすることで、他のオブジェクトのコライダーの表面にスナップできます。
これを使うと、目印のシリンダーを素早く地面に配置できます。シリンダーオブジェクトでなく空のオブジェクトでもできますが、メッシュがある方がどこに置いたかわかりやすいです。
そして、空のゲームオブジェクトに目印のシリンダーとアイテムを置き換えるためのスクリプトを追加します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System;
public class SetUpItem : MonoBehaviour
{
[SerializeField] GameObject item;
[SerializeField] [Range(0f, 1f)] float capacity;
// Start is called before the first frame update
void Start()
{
// 0以上の整数がPointの数だけ並んだ配列
int[] array1 = Enumerable.Range(0, transform.childCount).ToArray();
// array1をシャッフルする
int[] array2 = array1.OrderBy(i => Guid.NewGuid()).ToArray();
// 配置するアイテムの数
int count = Mathf.FloorToInt(transform.childCount * capacity);
// アイテム配置
for (int n = 0; n < count; n++)
{
Instantiate(item, transform.GetChild(array2[n]).position, item.transform.rotation);
}
// 破壊
Destroy(gameObject);
/*
int n = 0;
foreach (int i in ary2)
{
if (n < count)
{
Instantiate(item, transform.GetChild(i).position, item.transform.rotation);
}
Destroy(transform.GetChild(i).gameObject);
}
*/
}
}
シリンダーの数はtransform.childCountで取得できます。その数だけ0以上の整数が並んだ配列をつくり、これをシャッフルします。
シャッフルされた配列の先頭からアイテムを配置したい分だけ値を取得していって、アイテムを置き換えるための目印のシリンダーのインデックスとして使います。
置き換えるアイテムの数はシリンダーの数に0~1の小数を掛けた整数部分の値にしています。0~1の値はインスペクタでスライダーを使って指定します。
スライダーの値を0.733にすると、目印のシリンダーのうち7個がアイテムと置き換わりました。最後に空のゲームオブジェクトを破壊することで、目印のシリンダーも消えます。
もう一度実行すると、違う組み合わせのシリンダーと置き換わりました。
参考:http://dobon.net/vb/dotnet/programing/arrayshuffle.html