code VR

Unity×VR(52)

スポンサーリンク

//tips

//Prefab.transform.SetParent周りの改修

Prefab.transform.SetParent外した場合の操作を見直していく。

GamePlayerが生成された後にGamePlayerManagerの傘下に入るので、まずはその内容を確認する。

using System.Collections.Generic;
using UnityEngine;

public class GamePlayerManager : MonoBehaviour
{
private List<GamePlayer> playerList = new List<GamePlayer>();

public GamePlayer this[int index] => playerList[index];
public int Count => playerList.Count;

private void OnTransformChildrenChanged()
{
// 子要素が変わったら、ネットワークオブジェクトのリストを更新する
playerList.Clear();
foreach (Transform child in transform)
{
playerList.Add(child.GetComponent<GamePlayer>());
}
}
}

オブジェクトを配列のように扱う方法としてインデクサーというものがあり、GamePlayer this[int index] => playerList[index];でプレイヤーオブジェクトを配列のように扱うことを可能にしている。

これにより各プレイヤーの区別ができる。ラムダ式も絡んでいるので少し複雑になっているが、基本的なインデクサーの取り扱いを見ていく。

基本の方は下記となる。

T this [int index] { set { ... } get { ... } }

アクセスレベル 戻り値の型 this[添字の型 添字]
{
set
{
// 値の変更時の処理
// value変数に代入された値が格納
}
get
{
// 値の取得時の処理
// 値はreturnキーワードを用いて返す

}
}

シンプルな名簿の例:

using System;

class NameList
{
private string[] list = new string[128];

public string this[int index] //既に生成されているものに干渉
{
get { return list[index]; } //listに干渉し、indexに基づき、list[index]を取得
set { list[index] = value; } //list[index]の書き換え
}
}
class Program
{
static void Main()
{
NameList list = new NameList();
list[0] = “ああ”;
list[1] = “いい”;
Console.WriteLine(list[0]); // 出力: ああ
Console.WriteLine(list[1]); // 出力: いい
}
}

これをベースに public GamePlayer this[int index] => playerList[index];を理解しようとすると=>部分が少し邪魔になっている。

=>がラムダ式と言えるのかは検索では出てこないので(大体は変数に代入するラムダ式が紹介されている)、マイクロソフトが使用している例で理解を深める。

using System;

// Using a string as an indexer value
class DayCollection
{
string[] days = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };

// Indexer with only a get accessor with the expression-bodied definition:
public int this[string day] => FindDayIndex(day);

private int FindDayIndex(string day)
{
for (int j = 0; j < days.Length; j++)
{
if (days[j] == day)
{
return j;
}
}

throw new ArgumentOutOfRangeException(
nameof(day),
$"Day {day} is not supported.\nDay input must be in the form \"Sun\", \"Mon\", etc");
}
}

A get accessor takes a string, the name of a day, and returns the corresponding integer. とあるのでindexerのgetの役割を関数private int FindDayIndex(string day)で行わせるために=> が使われている。

下記は

private List<GamePlayer> playerList = new List<GamePlayer>();
public GamePlayer this[int index] => playerList[index];

playerListを作成しておき、playerList[index]の各値にindexを持った各GamePlayerの格納を読み取る。

ここがsetではないのは別のメソッドで

foreach (Transform child in transform)
{
playerList.Add(child.GetComponent<GamePlayer>());
}
としてリストに追加設定がされているからである。

つまり、public GamePlayer this[int index] => playerList[index];の凄いところはオブジェクトをリスト項目のように順番をつけて扱うことを可能にしていること。

なので、UI表示とはあまり関係がないコードとなっている。

そもそものUI表示として、prefabから生成してInventoryUIを表示するのは、生成オブジェクトに名前表示させるのと同じ工程を踏むはずなので、サイトでの紹介が多い名前表示の例を確認し、自分で行なってみることでinventoryUIの方に適用していく。

新たなシーンを作成し、作成を進めていく。今回は子要素にcanvasを入れるのではなく、プレイヤーが生成されたらプレイヤーに貼り付けたコードから次のUI生成に進むという入れ子状で考えた。

Canvasとplaneとシーンスクリプトを貼り付けたemptyboxがあるシーンで試行する。

シーンにprefabを導入するスクリプトは下記。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PrefabUpdateScene : MonoBehaviour
{
public GameObject originObject; //prefab

private void Start()
{
var v = new Vector3(Random.Range(-3f, 3f), Random.Range(1f, 2f));

GameObject Prefab = Instantiate(originObject, v, Quaternion.identity);

}
}

プレイヤーprefabに下記を貼り付けUI生成。
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
using System;

public class PlayerManager : MonoBehaviour
{
//頭上のUIのPrefab
public GameObject PlayerUiPrefab;

//Localのプレイヤーを設定
public static GameObject LocalPlayerInstance;
//頭上UIオブジェクト
GameObject _uiGo;

void Awake()
{
PlayerManager.LocalPlayerInstance = this.gameObject;
}

void Start()
{
_uiGo = Instantiate(PlayerUiPrefab) as GameObject;
//_uiGo.GetComponent<PlayerUIScript>().UIParent();

Debug.Log(_uiGo.transform.position);
Debug.Log("a");
}

}
生成されたUIに下記を貼り付け、canvasの子要素にsetという流れにした。

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class PlayerUIScript : MonoBehaviour
{

//キャラの頭上に乗るように調整するためのOffset
public Vector3 ScreenOffset = new Vector3(0f, 0f, 0f);
public Text PlayerNameText;

PlayerManager _target;
//float _characterControllerHeight;
Transform _targetTransform;
Vector3 _targetPosition;

void Awake()
{
//this.GetComponent<Transform>().SetParent(GameObject.Find("Canvas").GetComponent<Transform>());
}

void Start()
{
var PlayerUIManager = GameObject.FindWithTag("CanvasUI").GetComponent<Transform>();
this.transform.SetParent(PlayerUIManager.transform,false);

Debug.Log("aaa");
Debug.Log(PlayerUIManager.transform);

}
/*
public void UIParent()
{
var PlayerUIManager = GameObject.FindWithTag("CanvasUI").GetComponent<Transform>();
this.transform.SetParent(PlayerUIManager.transform);
}
*/
void Update()
{
//もしPlayerがいなくなったらこのオブジェクトも削除
if (_target == null)
{
Destroy(this.gameObject);
return;
}
}

void LateUpdate()
{
//targetのオブジェクトを追跡する
if (_targetTransform != null)
{
_targetPosition = _targetTransform.position; //三次元空間上のtargetの座標を得る
//_targetPosition.y += _characterControllerHeight; //キャラクターの背の高さを考慮する//targetの座標から頭上UIの画面上の二次元座標を計算して移動させる
this.transform.position = Camera.main.WorldToScreenPoint(_targetPosition) + ScreenOffset;
}
}
}

ただ、canvasの子要素にUIが移動せず苦戦している。問題をシンプルにできた点はよし。

人気の記事

1

皆さん、ついに、エアラインでも、サブスクリプションが始まったのはご存じですか? まだ実験段階ですが、ANAが、定額全国住み放題サービスを提供する「ADDress」と組んで、国内線を4回まで定額利用可能 ...

2

無料でネットショップを開けるアプリとして多くの人に驚きを与えたBASE株式会社が、2019年10月25日東証マザーズに上場しました。2020年2月時点で90万店を超えるショップを抱えるまでに成長してい ...

3

2011年にサービスを開始してから圧倒的な成長率を誇るインテリア通販サイト 【FLYMEe/フライミー】を皆さんご存じでしょうか。 「自分のイメージするインテリア、本当に欲しいインテリアがどこにあるの ...

4

ついに、noteの月間アクティブユーザー数が4400万人(2020年3月時点)に到達しました。 そもそも、「note」とは、クリエイターが、文章やマンガ、写真、音声を投稿することができ、ユーザーはその ...

5

ボードゲームカフェが1日2回転で儲かるという記事をみつけたので興味を持ち、調べてみました。 まずは、需要がどれくらいあるのか、市場のようすからみていきましょう。 世界最大のボードゲーム市場はドイツで、 ...

-code, VR
-,

Copyright© BUSINESS HUNTER , 2023 All Rights Reserved Powered by AFFINGER5.