今は、マウスで押された場合になっているので、次はコントローラーで動くようにします
ElevatorSwitchForControllerスクリプトを追加
using UnityEngine;
public class ElevatorSwitchForController : MonoBehaviour
{
[Header("検出設定")]
[SerializeField] private float detectionRange = 5f; // 検出範囲
[SerializeField] private bool showGizmo = true; // 範囲を可視化するか
[SerializeField] public Elevator[] elevators; // 連携設定
[Header("表示するオブジェクト")]
[SerializeField] private GameObject targetObject; // 表示/非表示するオブジェクト
[SerializeField] private bool useThisObject = false; // このオブジェクト自体を表示/非表示するか
[Header("回転設定")]
[SerializeField] private bool smoothRotation = true; // なめらかな回転にするか
[SerializeField] private float rotationSpeed = 5f; // 回転速度
[SerializeField] private bool lockYAxis = false; // Y軸回転のみにするか(水平回転のみ)
[SerializeField] private Vector3 rotationOffset = Vector3.zero; // 回転のオフセット
private Transform player; // プレイヤーのTransform
private bool playerInRange = false; // プレイヤーが範囲内にいるか
private GameObject objectToControl; // 制御するオブジェクト
private bool button = false; // ボタンを反応させるようにする
void Start()
{
// プレイヤーを検索
FindPlayer();
// 制御するオブジェクトを決定
if (useThisObject)
{
objectToControl = gameObject;
}
else if (targetObject != null)
{
objectToControl = targetObject;
}
else
{
Debug.LogWarning("表示するオブジェクトが設定されていません。");
return;
}
// 初期状態では非表示
objectToControl.SetActive(false);
}
void Update()
{
if (player == null)
{
FindPlayer();
return;
}
CheckPlayerDistance();
if (playerInRange && objectToControl.activeInHierarchy)
{
LookAtPlayer();
}
if (button == true)
{
if ((Input.GetKeyDown(KeyCode.Joystick1Button2)))
{
foreach (var elevator in elevators)
{
elevator.MoveUp();
}
}
}
}
private void FindPlayer()
{
GameObject playerObject = GameObject.FindGameObjectWithTag("Player");
if (playerObject != null)
{
player = playerObject.transform;
Debug.Log("プレイヤーを見つけました: " + playerObject.name);
}
else
{
Debug.LogWarning("'Player'タグの付いたオブジェクトが見つかりません。");
}
}
private void CheckPlayerDistance()
{
if (player == null || objectToControl == null) return;
float distance = Vector3.Distance(transform.position, player.position);
bool shouldBeActive = distance <= detectionRange;
if (shouldBeActive && !playerInRange)
{
// プレイヤーが範囲内に入った
playerInRange = true;
objectToControl.SetActive(true);
Debug.Log("プレイヤーが範囲内に入りました。オブジェクトを表示します。");
button = true;
}
else if (!shouldBeActive && playerInRange)
{
// プレイヤーが範囲外に出た
playerInRange = false;
objectToControl.SetActive(false);
Debug.Log("プレイヤーが範囲外に出ました。オブジェクトを非表示にします。");
}
}
private void LookAtPlayer()
{
if (player == null) return;
// プレイヤーへの方向ベクトルを計算
Vector3 direction = player.position - objectToControl.transform.position;
// Y軸をロックする場合
if (lockYAxis)
{
direction.y = 0;
}
// 方向ベクトルが0の場合は処理しない
if (direction.magnitude < 0.01f) return;
// 目標の回転を計算
Quaternion targetRotation = Quaternion.LookRotation(direction);
// オフセットを適用
if (rotationOffset != Vector3.zero)
{
targetRotation *= Quaternion.Euler(rotationOffset);
}
// なめらかな回転 or 即座に回転
if (smoothRotation)
{
objectToControl.transform.rotation = Quaternion.Slerp(
objectToControl.transform.rotation,
targetRotation,
rotationSpeed * Time.deltaTime
);
}
else
{
objectToControl.transform.rotation = targetRotation;
}
}
// 検出範囲を変更する外部メソッド
public void SetDetectionRange(float newRange)
{
detectionRange = newRange;
}
// プレイヤーが範囲内にいるかを取得
public bool IsPlayerInRange()
{
return playerInRange;
}
// Gizmoで検出範囲を表示(エディタ上でのデバッグ用)
void OnDrawGizmosSelected()
{
if (!showGizmo) return;
// 検出範囲を表示
Gizmos.color = playerInRange ? Color.green : Color.yellow;
Gizmos.DrawWireSphere(transform.position, detectionRange);
// プレイヤーとの接続線を表示
if (player != null && playerInRange)
{
Gizmos.color = Color.red;
Gizmos.DrawLine(transform.position, player.position);
if (objectToControl != null && objectToControl.activeInHierarchy)
{
Gizmos.color = Color.blue;
Gizmos.DrawRay(objectToControl.transform.position, objectToControl.transform.forward * 2f);
}
}
}
void OnDrawGizmos()
{
if (!showGizmo) return;
// 常に検出範囲を薄く表示
Gizmos.color = new Color(1f, 1f, 0f, 0.1f);
Gizmos.DrawSphere(transform.position, detectionRange);
}
}

DetactionRange 検出範囲の半径
ShowGizmo エディタ上で検出範囲を見えるようにする
TargetObject 動かしたいオブジェクトを入れる
UseThisObject 自分自身を制御する
SmoothRotation なめらかに回転させる
RotationSpeed 回転速度を設定
LockYAxis 水平回転のみ(Y軸固定)
RotationOffset 回転のオフセット

現在の様子
このように、いろいろ作れました!
これからもどんどん作っていきます
エレベーターの目的地をGameObjectを設定するのがめんどくさかったので数字に変更!
エレベータープログラム
using System.Collections;
using UnityEngine;
public class Elevator : MonoBehaviour
{
[Header("移動設定")]
[SerializeField] private float moveSpeed = 2f; // 移動速度
[SerializeField] private float arrivalThreshold = 0.01f; // 到着とみなす距離
[SerializeField] private float waitTime = 5f; // 待機時間
[SerializeField] private float moveDistance = 5f; // Y座標移動距離
[Header("連携設定")]
[SerializeField] public ElevatorSwitch[] elevators; // スイッチと連携する場合用
private bool isMoving = false; // 移動中フラグ
private bool isAtTop = false; // 上にいるかどうか
private Vector3 startPosition; // 初期位置
private Vector3 topPosition; // 上の位置
void Start()
{
startPosition = transform.position; // 初期位置を記録
topPosition = startPosition + Vector3.up * moveDistance; // 上の位置を計算
isMoving = false; // 最初は停止状態
isAtTop = false; // 下にいる状態からスタート
}
void Update()
{
if (isMoving)
{
Vector3 destination = isAtTop ? startPosition : topPosition;
// 目的地に向かって移動
transform.position = Vector3.MoveTowards(
transform.position,
destination,
moveSpeed * Time.deltaTime
);
// 到着判定(距離が十分に近ければ到着とみなす)
if (Vector3.Distance(transform.position, destination) < arrivalThreshold)
{
transform.position = destination; // ぴったり位置を合わせる
isMoving = false;
if (!isAtTop)
{
isAtTop = true;
StartCoroutine(WaitAndMoveDown()); // 上に着いたら待ってから戻る
}
else
{
isAtTop = false;
EnableSwitches(); // 下に着いたらスイッチを再有効化
}
}
}
}
private IEnumerator WaitAndMoveDown()
{
yield return new WaitForSeconds(waitTime); // 一時停止
isMoving = true; // 下への移動を再開
}
private void EnableSwitches()
{
// スイッチを再びクリック可能にする
foreach (var elevatorSwitch in elevators)
{
elevatorSwitch.EnableClick();
}
}
// 外部から呼び出すことでエレベーターを上昇させる
public void MoveUp()
{
if (!isMoving && !isAtTop)
{
isMoving = true;
}
}
}

次は、GameObjectを設定するのではなく、MoveDistanceのところで動き幅を設定するようにした!
カメラを回転できるようにする
Playerのスクリプトを書き換える!
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("移動設定")]
[SerializeField] private float moveSpeed; // 移動速度
[SerializeField] private float jumpForce; // ジャンプ力
[SerializeField] private float deadZone = 0.1f; // コントローラーのデッドゾーン
[Header("カメラ設定")]
[SerializeField] private float mouseSensitivity = 2f; // マウス感度
[SerializeField] private float controllerSensitivity = 100f; // コントローラー感度
[SerializeField] private float maxLookUpAngle = 80f; // 上を向く最大角度
[SerializeField] private float maxLookDownAngle = -80f; // 下を向く最大角度
[SerializeField] private Camera playerCamera; // プレイヤーカメラの参照
[SerializeField] private float cameraHeight = -0.5f; // カメラの高さオフセット
private Rigidbody rb; // プレイヤーのRigidbody
private bool isGrounded; // 地面に接しているかどうか
private float verticalRotation = 0f; // カメラの縦回転
void Start()
{
rb = GetComponent<Rigidbody>();
// カメラが設定されていない場合、子オブジェクトから探す
if (playerCamera == null)
{
playerCamera = GetComponentInChildren<Camera>();
}
// カメラの位置を調整(視点を下げる)
if (playerCamera != null)
{
Vector3 cameraPos = playerCamera.transform.localPosition;
cameraPos.y = cameraHeight;
playerCamera.transform.localPosition = cameraPos;
}
// カーソルをロック(任意)
Cursor.lockState = CursorLockMode.Locked;
}
void Update()
{
Move();
Jump();
CameraLook();
}
void Move()
{
Vector3 moveDirection = Vector3.zero;
// キーボード入力
if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W))
{
moveDirection += transform.forward;
}
if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S))
{
moveDirection -= transform.forward;
}
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
{
moveDirection -= transform.right;
}
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
{
moveDirection += transform.right;
}
// コントローラー入力(左スティック)
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
// デッドゾーン処理
if (Mathf.Abs(horizontal) > deadZone)
{
moveDirection += transform.right * horizontal;
}
if (Mathf.Abs(vertical) > deadZone)
{
moveDirection += transform.forward * vertical;
}
Vector3 move = moveDirection.normalized * moveSpeed;
Vector3 velocity = rb.linearVelocity;
rb.linearVelocity = new Vector3(move.x, velocity.y, move.z);
}
void Jump()
{
// キーボード(スペースキー)またはコントローラー(×ボタン)でジャンプ
if ((Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.Joystick1Button1)) && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
isGrounded = false;
}
}
void CameraLook()
{
// マウス入力
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity;
// コントローラー入力(右スティック)
float rightStickX = 0f;
float rightStickY = 0f;
// 複数の軸名を試行(お好みの軸名を追加/変更可能)
string[] rightStickXNames = { "Right Stick X", "Joy1 Axis 4", "RightStickX", "Mouse X" };
string[] rightStickYNames = { "Right Stick Y", "Joy1 Axis 5", "RightStickY", "Mouse Y" };
foreach (string axisName in rightStickXNames)
{
try
{
rightStickX = Input.GetAxis(axisName);
break;
}
catch (System.ArgumentException) { }
}
foreach (string axisName in rightStickYNames)
{
try
{
rightStickY = Input.GetAxis(axisName);
break;
}
catch (System.ArgumentException) { }
}
// デッドゾーン処理とコントローラー入力の適用
if (Mathf.Abs(rightStickX) > deadZone)
{
// 右スティック横軸 → 水平回転(左右)
mouseX += rightStickX * controllerSensitivity * Time.deltaTime;
}
if (Mathf.Abs(rightStickY) > deadZone)
{
// 右スティック縦軸 → 垂直回転(上下)
mouseY += rightStickY * controllerSensitivity * Time.deltaTime; // 反転を削除
}
// 水平回転(プレイヤー全体を回転)
transform.Rotate(Vector3.up * mouseX);
// 垂直回転(カメラのみ回転)
verticalRotation -= mouseY;
verticalRotation = Mathf.Clamp(verticalRotation, maxLookDownAngle, maxLookUpAngle);
if (playerCamera != null)
{
playerCamera.transform.localRotation = Quaternion.Euler(verticalRotation, 0f, 0f);
}
}
void OnCollisionEnter(Collision collision)
{
// 地面に着いたらジャンプ可能にする
if (collision.gameObject.CompareTag("Ground") || collision.gameObject.CompareTag("Block"))
{
isGrounded = true;
}
}
public void Ground()
{
isGrounded = true;
}
}