Unity新手求助:角色切换相机适配及场景加载故障排查
Solution for Unity Character Selection & Camera Issues
1. Fix Camera Reference & Positioning Problems
CameraFollow Field Showing "None"
This is not normal—it means the reference is unassigned. Fix it by:
- Select the GameObject with the
CharacterSelectionscript in the Unity Editor. - Drag the Main Camera (or the camera with the
CameraFollowcomponent) into thecameraFollowfield in the Inspector.
Camera Angle & Position Adjustment
Update the CameraFollow script to ensure proper framing and rotation for all character sizes:
public class CameraFollow : MonoBehaviour { [SerializeField] Transform player; [SerializeField] Vector3 offSet; [SerializeField] float rotationSmoothness = 3f; void Update() { if (player == null) return; // Maintain position relative to the character transform.position = player.position + offSet; // Lock camera to face the character (fixes angle issues) Quaternion targetRotation = Quaternion.LookRotation(player.position - transform.position); transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, rotationSmoothness * Time.deltaTime); } public void SetFollowTarget(Transform player, Vector3 offSet) { this.player = player; this.offSet = offSet; } }
- For each character prefab, open the
Charactercomponent and adjust theoffSetvalues: taller characters need higher Y offsets and further Z offsets to fit in the frame.
2. Fix Character Loading Failure
The core issue is missing PlayerPrefs saving in the selection menu. Update the CharacterSelection script to persist the selected character:
public class CharacterSelection : MonoBehaviour { [SerializeField] CameraFollow cameraFollow; public Character[] characters; public int selectedCharacter = 0; void Start() { // Load saved selection when menu opens selectedCharacter = PlayerPrefs.GetInt("selectedCharacter", 0); // Ensure only the selected character is active for (int i = 0; i < characters.Length; i++) { characters[i].gameObject.SetActive(i == selectedCharacter); } UpdateCameraForSelectedCharacter(); } public void NextCharacter() { characters[selectedCharacter].gameObject.SetActive(false); selectedCharacter = (selectedCharacter + 1) % characters.Length; characters[selectedCharacter].gameObject.SetActive(true); SaveSelection(); UpdateCameraForSelectedCharacter(); } public void PreviousCharacter() { characters[selectedCharacter].gameObject.SetActive(false); selectedCharacter--; if (selectedCharacter < 0) selectedCharacter += characters.Length; characters[selectedCharacter].gameObject.SetActive(true); SaveSelection(); UpdateCameraForSelectedCharacter(); } private void SaveSelection() { PlayerPrefs.SetInt("selectedCharacter", selectedCharacter); PlayerPrefs.Save(); } private void UpdateCameraForSelectedCharacter() { if (cameraFollow == null) return; cameraFollow.SetFollowTarget(characters[selectedCharacter].transform, characters[selectedCharacter].OffSet); } }
Additional LoadCharacter Checks
- Assign All References: In the
LoadCharacterGameObject's Inspector, assign the Main Camera tocameraFollow, populatecharacterPrefabsin the same order asCharacterSelection'scharactersarray, and set thespawnPointandlabelfields. - Debug the Selection: Add a log to confirm the loaded index:
void Start() { int selectedCharacter = PlayerPrefs.GetInt("selectedCharacter", 0); Debug.Log("Loading character index: " + selectedCharacter); // Rest of the code... } - Check Console for Errors: Null reference errors will stop script execution—fix any unassigned fields first.
3. Reserve Space for Unique Character Actions & Movement
Use ScriptableObjects to manage character-specific data cleanly:
Step 1: Create Character Data Asset
using UnityEngine; [CreateAssetMenu(fileName = "New Character Data", menuName = "Character/Character Data")] public class CharacterData : ScriptableObject { public float movementSpeed; public RuntimeAnimatorController animatorController; // Add fields for unique actions: e.g., GameObject[] abilityPrefabs, float jumpHeight }
Step 2: Update Character Component
public class Character : MonoBehaviour { [SerializeField] Vector3 offSet; public Vector3 OffSet => offSet; [SerializeField] CharacterData characterData; public CharacterData CharacterData => characterData; void Start() { // Initialize animator with character-specific controller Animator animator = GetComponent<Animator>(); if (animator != null && characterData.animatorController != null) { animator.runtimeAnimatorController = characterData.animatorController; } } }
Step 3: Build Movement/Action Systems
Example movement script using character data:
public class CharacterMovement : MonoBehaviour { private Character character; private Rigidbody rb; void Start() { character = GetComponent<Character>(); rb = GetComponent<Rigidbody>(); } void FixedUpdate() { float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); Vector3 movement = new Vector3(horizontal, 0, vertical) * character.CharacterData.movementSpeed * Time.fixedDeltaTime; rb.MovePosition(transform.position + movement); } }
Usage:
- Right-click in the Project window →
Character→Character Datato create unique data assets for each character. - Assign these assets to the
characterDatafield in each character prefab'sCharactercomponent. - Add new fields to
CharacterDataas needed for unique actions or stats.
内容的提问来源于stack exchange,提问作者Raffaele Ozunu
相关产品推荐
相关产品推荐

