This document is about: PUN 2
SWITCH TO

PUN Classic (v1)、PUN 2、Boltはメンテナンスモードとなっております。Unity2022についてはPUN 2でサポートいたしますが、新機能が追加されることはありません。お客様のPUNプロジェクトおよびBoltプロジェクトが停止することはなく、将来にわたってパフォーマンス性能が落ちることはありません。 今後の新しいプロジェクトについては、Photon FusionまたはQuantumへ切り替えていただくようよろしくお願いいたします。

6 - プレイヤーのカメラワーク

このセクションプレイヤーを追従するCameraWorkスクリプトを作成する方法を説明します。

このセクションはネットワーキングとは関係がないため、簡潔に説明します。

CameraWorkスクリプトを作成

  1. CameraWorkという名前の新しいC#スクリプトを作成します。
  2. CameraWorkの内容を以下のように置換します。

C#

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CameraWork.cs" company="Exit Games GmbH">
//   Part of: Photon Unity Networking Demos
// </copyright>
// <summary>
//  Used in PUN Basics Tutorial to deal with the Camera work to follow the player
// </summary>
// <author>[email protected]</author>
// --------------------------------------------------------------------------------------------------------------------

using UnityEngine;

namespace Photon.Pun.Demo.PunBasics
{
/// <summary>
/// Camera work. Follow a target
/// </summary>
public class CameraWork : MonoBehaviour
{
      #region Private Fields

    [Tooltip("The distance in the local x-z plane to the target")]
    [SerializeField]
    private float distance = 7.0f;

    [Tooltip("The height we want the camera to be above the target")]
    [SerializeField]
    private float height = 3.0f;

    [Tooltip("Allow the camera to be offseted vertically from the target, for example giving more view of the sceneray and less ground.")]
    [SerializeField]
    private Vector3 centerOffset = Vector3.zero;

    [Tooltip("Set this as false if a component of a prefab being instanciated by Photon Network, and manually call OnStartFollowing() when and if needed.")]
    [SerializeField]
    private bool followOnStart = false;

    [Tooltip("The Smoothing for the camera to follow the target")]
    [SerializeField]
    private float smoothSpeed = 0.125f;

      // cached transform of the target
      Transform cameraTransform;

  // maintain a flag internally to reconnect if target is lost or camera is switched
  bool isFollowing;

  // Cache for camera offset
  Vector3 cameraOffset = Vector3.zero;

      #endregion

      #region MonoBehaviour Callbacks

      /// <summary>
      /// MonoBehaviour method called on GameObject by Unity during initialization phase
      /// </summary>
      void Start()
  {
    // Start following the target if wanted.
    if (followOnStart)
    {
      OnStartFollowing();
    }
  }


  void LateUpdate()
  {
    // The transform target may not destroy on level load,
    // so we need to cover corner cases where the Main Camera is different everytime we load a new scene, and reconnect when that happens
    if (cameraTransform == null && isFollowing)
    {
      OnStartFollowing();
    }

    // only follow is explicitly declared
    if (isFollowing) {
      Follow ();
    }
  }

  #endregion

  #region Public Methods

  /// <summary>
  /// Raises the start following event.
  /// Use this when you don't know at the time of editing what to follow, typically instances managed by the photon network.
  /// </summary>
  public void OnStartFollowing()
  {          
    cameraTransform = Camera.main.transform;
    isFollowing = true;
    // we don't smooth anything, we go straight to the right camera shot
    Cut();
  }

  #endregion

  #region Private Methods

  /// <summary>
  /// Follow the target smoothly
  /// </summary>
  void Follow()
  {
    cameraOffset.z = -distance;
    cameraOffset.y = height;

      cameraTransform.position = Vector3.Lerp(cameraTransform.position, this.transform.position +this.transform.TransformVector(cameraOffset), smoothSpeed*Time.deltaTime);

      cameraTransform.LookAt(this.transform.position + centerOffset);
  }


  void Cut()
  {
    cameraOffset.z = -distance;
    cameraOffset.y = height;

    cameraTransform.position = this.transform.position + this.transform.TransformVector(cameraOffset);

    cameraTransform.LookAt(this.transform.position + centerOffset);
  }
  #endregion
}
}
  1. スクリプトCameraWorkを保存します。

The logic behind following the player is simple. We compute the desired camera position with added offset to fall behind using the Distance and above using the Height. Then it uses Lerping for smoothing out the movement to catch up with the desired position and finally, a simple LookAt for the camera to always point at the Player.

Aside the Camera work itself, something important is also set up; the ability to control when the behaviour should actively follow the player.
And this is important to understand: When would we want to have the camera to follow the player?

いつもいつもプレイヤーを追従しているとどうなるのか考えてみましょう。
プレイヤーが多くいるルームに接続すると、相手のプレイヤーインスタンスのCameraWorkスクリプトが、自分のプレイヤーを写すため「メインカメラ」を制御しようとぶつかり合います。
このような事態は避け、コンピューターの前にいるユーザーを表すローカルプレイヤーのみを追従すべきです。

1つのカメラに対して複数のプレイヤーインスタンスが存在する場合の問題を把握できたので、それを防ぐ方法を以下で説明します。

  1. ローカルプレイヤーにのみCameraWorkスクリプトを添付します。
  2. 追従するプレイヤーがローカルかどうかに応じてオンとオフを切り替え、CameraWorkの動作を制御します。
  3. CameraWorkをカメラに取り付け、シーンの中にローカルプレイヤーインスタンスがある場合は注意して、そのプレイヤーのみを追従するようにします。

他にも方法はありますが、これらの3つの方法の中から選ぶとしたら2つ目のオプションをお勧めします。
3つの方法に大差はありませんが、2つ目のオプションはコーディングの量が最も少なく非常に高い柔軟性があります。

  • フィールドfollowOnStartを公開しましたので、非ネットワークされた環境で使用する場合trueに設定してください。例:テストシーンや、まったく異なるシナリオ
  • ネットワークベースのゲームで動作する場合、プレイヤーがローカルであると検出した場合にはパブリックメソッドOnStartFollowing()を呼び出します。
    これは作成されたスクリプトPlayerManagerで実行されます。このスクリプトについてはプレイヤーネットワーキングの章で説明します。

前に戻る.

Back to top