你不能直接将场景引用附加到ScriptableObject
或任何资产上。
但是你可以采取相反的方式:将ScriptableObject
引用提供给摄像机,并使其告诉该ScriptableObject
自己的引用:
[ExecuteInEditModo]
[RequireComponent(typeof(Camera))]
public class CameraSetter : MonoBehaviour
{
[SerializeField] private MainCamera mainCameraAsset;
private void Awake ()
{
mainCameraAsset.Camera = GetComponent<Camera>();
}
}
请引用MainCamera
实例中的mainCameraAsset
。
你为什么不使用Camera.main而使用ScriptableObject
?
为不同场景创建地图
如果您想要类似于存储每个场景不同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;
}
and in the setter use SceneManager.GetActiveScene
[ExecuteInEditModo]
[RequireComponent(typeof(Camera))]
public class CameraSetter : MonoBehaviour
{
[SerializeField] private MainCamera mainCameraAsset;
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;
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;
}
public void Set(Camera camera, CharacterController characterController, Transform characterTransform)
{
mainCamera = camera;
controller = characterController;
transform = characterTransform;
}
}
你可以创建一个基础的Setter类,如下所示:
public abstract class SetterBase<T> : MonoBehaviour where T : Component
{
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;
public Camera camera;
public Transform transform;
public CharacterController controller;
private void Awake()
{
references.Set(camera, controller, transform);
}
}
Scene1_mainCamera
,Scene1_menuCamera
,Scene2_camera
等。如果您正在谈论不同的组件类型...是的,您需要为每种类型创建一个setter。 - derHugo