ゲームで最も重要なのはプレイヤーの反応を反映すること!ここではキャラの動きとは別で、プレイヤーがアイテムを取ったり、ボタンを付けたり消したりするときの動きとなるインタラクションの導入を行います。
作れるもの
インタラクションのサンプルとして、アイテムを取得する動作があります。
画面での様子
今回は丸い球をアイテムと見立て、近づいてインタラクションボタンを押すことで取得した(非表示になった)と見せています。実際のゲームではアイテムに置き換えて実装してみてください。
学べる内容
- インターフェースの作成とその実装
- 当たり判定のレイヤー設定
プレイヤー側の実装
インタラクションの処理は、今後様々な処理と組み合わせて作成することになります。また触る側と触られる側療法をつなぐためのインターフェースを用意して、そちらを仲介しながらアクションできるようにします。
インターフェースの作成
インターフェースはカスタマイズ可能なパーツです。今回は以下の機能を持たせます
- インタラクション(なんらかのアクションを仕掛ける)
- フォーカスが合う(何からフォーカスされたか、アクターのゲームオブジェクトを引数に持たせる)
- フォーカスが外れる
using UnityEngine;
public interface IFPInteraction
{
public string ActionTitle { get; }
void OnInteract();
void OnFocusIn(GameObject actor);
void OnFocusOut();
}
インタラクションを仕掛ける方
プレイヤーがインタラクションを仕掛けることになると思います。機能やコードの簡単な説明は以下
- カメラの見ている方向
- インタラクションを及ぼせる距離
- インタラクションできる当たり判定のレイヤーを指定
- インタラクションのキーを指定
- 原則としてインタラクションは1つだけに起こせる(同時は無し)
using UnityEngine;
public class FPInteraction : FPComponentBase
{
[SerializeField] private Vector3 interactionRayOrigin = new Vector3(0.5f, 0.5f, 0.5f);
[SerializeField] private float interactionRayDistance = 2.0f;
[SerializeField] private LayerMask interactionLayerMask = default;
[SerializeField] private KeyCode interactionKey = KeyCode.E;
private IFPInteractable currentInteractable = null;
public IFPInteractable CurrentInteractable => currentInteractable;
private void Update()
{
Ray ray = Controller.PlayerCamera.ViewportPointToRay(interactionRayOrigin);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, interactionRayDistance, interactionLayerMask))
{
IFPInteractable interactable = hit.collider.GetComponent<IFPInteractable>();
if (interactable != null)
{
if (currentInteractable != interactable)
{
if (currentInteractable != null)
{
currentInteractable.OnFocusOut();
}
currentInteractable = interactable;
currentInteractable.OnFocusIn(gameObject);
}
}
else
{
if (currentInteractable != null)
{
currentInteractable.OnFocusOut();
currentInteractable = null;
}
}
}
else
{
if (currentInteractable != null)
{
currentInteractable.OnFocusOut();
currentInteractable = null;
}
}
if (Input.GetKeyDown(interactionKey))
{
if (currentInteractable != null)
{
currentInteractable.OnInteract();
}
}
}
}
プレイヤー側にセット
スクリプトの準備が出来たらプレイヤーのインスペクターにセットしておきましょう。実際に動かせるのはもう少し先になります。パラメータはデフォルトで大丈夫です。
スクリプト2つは用意する順番によってはエラーが発生します。
間違えないようにコピーして使ってください
今回はかなり機能を絞っていますが、実際にはもう少し情報をもたせたりします。自分のゲームに合ったカスタマイズをしてくださいね
アクションされる側
インターフェースを実際に利用する方の実装になります。今回は球にインタラクションすると取得したとして非表示にしてみたいと思います。
取得するアイテムのサンプルスクリプト(SampleTakeObject)
ここではアイテムを取得するスクリプトを作成します。このスクリプトはプロジェクト側に依存させるものなので、異なるフォルダかSampleフォルダなどを別途用意して配置してください。
取得された風にするため、インタラクションを起こすと非アクティブにします。
using UnityEngine;
public class SampleTakeObject : MonoBehaviour, IFPInteractable
{
public string ActionTitle => "Take Object";
public void OnFocusIn(GameObject actor)
{
Debug.Log("OnFocusIn");
}
public void OnFocusOut()
{
Debug.Log("OnFocusOut");
}
public void OnInteract()
{
Debug.Log("OnInteract");
gameObject.SetActive(false);
}
}
フォーカスの出入りでログが表示されますが、マテリアルやシェーダーを変えると、なんのオブジェクトに注目しているかわかりやすく表現できるようになります。
オブジェクトの設定
今回はSphereを取得アイテムと見立てて実装したいと思います。お好みでマテリアルを設定してアイテムっぽくしてみてください。
- 球体を作成
- Create>3D Object>Sphere
- 名前変更:DummyItem
- キャラクターの見える位置に配置
- 高さを1ぐらいにする
- お好みでマテリアルを作成してあてがいます。見やすくなります
- DummyItemの設定
- レイヤーを変更
- レイヤー一覧からAdd Layer
- 空いているところにInteractableという名前のレイヤーを追加
- もう一度DummyItemのインスペクターを表示してレイヤー:Interactableに変更
- Colliderの有無を確認
- 基本的には自動で配置されています。
- 球体にフィットした当たり判定(SphereCollier)が配置されていることを確認してください
- SampleTakeObjectコンポーネントをアタッチ
- レイヤーを変更
動作確認!
あとは設定整えて動かすだけです!
プレイヤー側のインタラクション設定
テスト実装する前にプレイヤー側にインタラクションを起こせるレイヤーを指定します。お好みでボタンも変えてください。私はマウスの左クリックで反応するように変更しています。
動作確認
設定が済んだら、実際に動かしてみてインタラクションボタンを押してSphereが非表示になるのを確認してみてください。
コメント