前提・実現したいこと
初心者ですがよろしくお願いします。
unityでオブジェクト(テレポーター)に接触した場合、シーンAからシーンBへプレイヤー(追尾するカメラ等を含む)を移動させたいと思っています。
今はシーンAとシーンB両方にプレハブのプレイヤーを配置し切り替えているのですが、それでは移動ではなく切り替えになってしまいます。
将来的にプレイヤーのステータス(ダメージ情報含む)や所持品なども移動させたいです。
それとシーンAのテレポーター東は、シーンBのテレポーター西に繋がるなど場所の指定をしたいです。
出来ればお手本のスクリプトを記入していただけると大変助かります。
試したこと
現在使用しているスクリプトは以下の通りです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Teleport : MonoBehaviour {
private void OnTriggerEnter(Collider other)
{
Debug.Log("移動した");
SceneManager.LoadScene("シーンA");
}
}
補足情報(FW/ツールのバージョンなど)
unity 2018.1.ob13
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
プレイヤー退避用のシーンに移動する、またはDontDestroyOnLoadでプレイヤーの破壊を防いで、シーン移動後に新しいシーンに復帰させるというのではどうでしょうか?
テレポーターのスクリプト
テレポーターにアタッチ後、インスペクタであらかじめ移動先シーン名・移動先テレポーター名を設定しておく
using UnityEngine;
namespace Teleport
{
public class Teleporter : MonoBehaviour
{
public string DestinationScene;
public string DestinationTeleporter;
}
}
プレイヤーのスクリプト
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Teleport
{
public class Player : MonoBehaviour
{
public float Speed = 4.0f;
private Transform cameraTransform;
private string destinationSceneName;
private string destinationTeleporterName;
private bool ignoreTriggerEnterOnce;
private new Rigidbody rigidbody;
private Vector3 velocity;
private void OnTriggerEnter(Collider other)
{
// シーン移動直後に再びテレポーターと接触した際に、またシーン移動してしまうと
// 困るので、OnTriggerEnter無視モードを設ける
// もし無視モードなら無視モードを解除して、後は何もしない
if (this.ignoreTriggerEnterOnce)
{
this.ignoreTriggerEnterOnce = false;
return;
}
// テレポーターには「Teleporter」タグを付けておき、接触相手を識別する
if (other.tag != "Teleporter")
{
return;
}
// 接触相手からTeleporterを取得、失敗すれば何もしない
var teleporter = other.GetComponent<Teleporter>();
if (teleporter == null)
{
return;
}
// 接触相手のTeleporterを見て、移動先シーン・移動先テレポーター名を調べる
this.destinationSceneName = teleporter.DestinationScene;
this.destinationTeleporterName = teleporter.DestinationTeleporter;
// OnTriggerEnter無視モードにする
this.ignoreTriggerEnterOnce = true;
// シーン遷移で自身が削除されないようにする
DontDestroyOnLoad(this.gameObject);
// シーン移動後のイベントハンドラーをセットしてからシーンを移動
SceneManager.sceneLoaded += this.OnSceneLoaded;
SceneManager.LoadScene(this.destinationSceneName);
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
// イベントハンドラーを解除
SceneManager.sceneLoaded -= this.OnSceneLoaded;
// 設計にもよるでしょうが、初期シーンにプレイヤーを直接配置していると
// 初期シーン戻ってきた時にプレイヤーがもう一人現れるかもしれません
// このへんは設計に応じて適宜対処してみてください
foreach (var player in GameObject.FindGameObjectsWithTag("Player"))
{
if (player != gameObject)
{
Destroy(player);
}
}
// 移動先のテレポーターを探す
var destination = GameObject
.FindGameObjectsWithTag("Teleporter")
.FirstOrDefault(o => o.name == this.destinationTeleporterName);
if (destination == null)
{
Debug.LogErrorFormat("Teleporter {0} not found!", this.destinationTeleporterName);
}
else
{
// 自身の位置を移動先テレポーターの位置にセット
this.rigidbody.position = destination.transform.position;
}
// 自身を移動先シーンのヒエラルキーに移す
SceneManager.MoveGameObjectToScene(this.gameObject, SceneManager.GetSceneByName(this.destinationSceneName));
}
// 以下はプレイヤー操作用のコードですので、シーン間移動には関係ありません
// ご質問者さんの設計に合わせたやり方でやってみてください
private void Start()
{
this.rigidbody = this.GetComponent<Rigidbody>();
this.cameraTransform = this.GetComponentInChildren<Camera>().transform;
}
private void Update()
{
var forward = Vector3.Scale(this.cameraTransform.forward, new Vector3(1.0f, 0.0f, 1.0f)).normalized;
var right = this.cameraTransform.right;
this.velocity = ((Input.GetAxis("Horizontal") * right) + (Input.GetAxis("Vertical") * forward)) *
this.Speed;
}
private void FixedUpdate()
{
this.rigidbody.MovePosition(this.rigidbody.position + (this.velocity * Time.fixedDeltaTime));
}
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.34%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2018/09/08 21:15
問題なく実行できました。説明も丁寧でわかりやすく、本当に感謝します!
ありがとうございました!