您可以不直接将场景引用附加到 ScriptableObjects 或实际上任何资产。
但是你可以反过来:给相机 ScriptableObject 引用并让它告诉它自己对 ScriptableObject 的引用:
// This attribute makes this classes messages be executed also in editmode
// (= also of not in playmode)
[ExecuteInEditModo]
// Assure there is a Camera component
[RequireComponent(typeof(Camera))]
public class CameraSetter : MonoBehaviour
{
[SerializeField] private MainCamera mainCameraAsset;
// Called on initialize
// With [ExecuteInEditModo] also called on recompile
private void Awake ()
{
mainCameraAsset.Camera = GetComponent<Camera>();
}
}
并在mainCameraAsset 中引用您的MainCamera 实例。
您是否有理由不使用Camera.main 而不是ScriptableObject?
不同场景的地图
如果您想归档类似“管理器资产”之类的内容,按照 cmets 中的要求为每个场景存储不同的 Camera 参考(希望我理解正确),我会将您的 MainCamera 更改为类似
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/MainCamera",
order = 1)]
public class MainCamera : ScriptableObject
{
public List<SceneCameraPair> SceneCameraPairs = new List<SceneCameraPair>();
public Dictionary<string, Camera> sceneToCamera = new Dictionary<string, Camera>();
public void AddPair(SceneCameraPair pair)
{
if(SceneCameraPairs.Contains(pair)) return;
SceneCameraPairs.Add(pair);
sceneToCamera[pair.scene.path] = pair.camera;
}
public void ResetPairs()
{
SceneCameraPairs.Clear();
sceneToCamera.Clear();
}
}
[System.Serializable]
public class SceneCameraPair
{
public Scene scene;
public Camera camera;
}
在设置器中使用SceneManager.GetActiveScene
// This attribute makes this classes messages be executed also in editmode
// (= also of not in playmode)
[ExecuteInEditModo]
// Assure there is a Camera component
[RequireComponent(typeof(Camera))]
public class CameraSetter : MonoBehaviour
{
[SerializeField] private MainCamera mainCameraAsset;
// Called on initialize
// With [ExecuteInEditModo] also called on recompile
private void Awake ()
{
mainCameraAsset.AddPair(SceneManager.GetActiveScene, GetComponent<Camera>();
}
}
在稍后的场景中,您可以将列表与FirstOrDefault(不会引发异常,但如果找不到项目返回null)和Scene.path(因为场景名称可能相同)一起使用而且您不能直接比较scene,因为它的实例与引用的实例不同),例如
var camera = mainCameraReference.SceneCameraPairs.FirstOrDefault(pair => pair.scene.path == ScaneManager.GetActiveScene().path);
或字典之类的
var camera = mainCameraReference.sceneToCamera[ScaneManager.GetActiveScene().path];
各种类型
为了能够存储不同类型的各种引用(假设每种类型只有一个),您可以执行类似的操作,例如
[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/Data", order = 1)]
public class References : ScriptableObject
{
public Camera mainCamera;
public CharacterController controller;
public Transform transform;
// fix for the generic methods
// a bit dirty maybe but should work
public void Set(Component component)
{
if(component.GetType() == typeof(Camera))
{
mainCamera = (Camera) component;
}
else if(component.GetType() == typeof(CharacterController))
{
controller = (CharacterController) component;
}
else if(component.GetType() == typeof(Transform))
{
transform = (Transform) component;
}
}
public void Set(Camera camera)
{
mainCamera = camera;
}
public void Set(CharacterController characterController )
{
controller = characterController ;
}
public void Set(Transform characterTransform)
{
transform = characterTransform;
}
// or simply all at once
public void Set(Camera camera, CharacterController characterController, Transform characterTransform)
{
mainCamera = camera;
controller = characterController;
transform = characterTransform;
}
// etc
}
你可以拥有一个像这样的基本 setter 类
public abstract class SetterBase<T> : MonoBehaviour where T : Component
{
// unfortunately you can not serialize generics in
// the inspector so for now we stick with only one single ScriptableObject
public References references;
privtae void Awake()
{
SetReference<T>();
}
private void SetReference<T>() where T : Component
{
var component = GetComponent<T>();
references.Set(component);
}
}
现在您可以继承References 中存在的每种所需/类型的实现
public CameraSetter : SetterBase<Camera>
{
// doesn't have to do anything else ... but could
}
和
public TransformSetter : SetterBase<Transform>
{
// doesn't have to do anything else ... but could
}
等
或者
(这就是为什么我为所有事情添加了一个二传手)你可以让一个经理来处理所有事情
public class ReferenceSetter : MonoBehaviour
{
public References references;
// Reference those in the inspector as usual
public Camera camera;
public Transform transform;
public CharacterController controller;
private void Awake()
{
references.Set(camera, controller, transform);
}
}