I’m having a tough time figuring out what I’m doing wrong here so any help is appreciated. I’m a self-taught dev who works alone, so please be easy on me
Background
I’m trying to create a Character system for my little RPG project. The goal is to have Character “templates” which I can build in the editor, then instance and modify in-game.
I’m using a lot of scriptable objects in my Resources folder, which are attached to a game object called CharacterDB. At runtime, the CharacterDB script creates new instances of the scriptable objects, then creates new non-Monobehaviour Character objects at runtime.
In the CharacterDB, I have a method called GetCharacter, which takes a GUID, and should return a new copy of the Character. For one in-game use, I created a CharacterPrefab class, which I want to call the Character data from CharacterDB, then overwrite parts of it when I call an Initialize method. Example use case would be changing the name of a character from “Monster001” to "
Problem
When I change the name in CharacterPrefab, it’s changing the name of the source data stored in the dictionary in CharacterDB. Anyhow, here’s my code:
CharacterDB
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterDB : MonoBehaviour
{
[SerializeField] private List<CharacterSO> _characterSOList;
private Dictionary<string, Character> _charactersDict = new Dictionary<string, Character>();
private ItemDB _itemDB;
private void Awake(){
_itemDB = FindObjectOfType<ItemDB>();
if (_itemDB == null){
Debug.Log("Cannot locate ItemDB.");
}
}
private void Start(){
foreach (CharacterSO characterSO in _characterSOList){
CharacterSO newCharacterSO = Instantiate(characterSO);
bool isValid = ValidateData(characterSO);
if (!isValid){
throw new System.Exception($"{newCharacterSO} has invalid item data. Fix and restart.");
}
else{
List<Item> items = new List<Item>();
foreach (string id in newCharacterSO.StartingItemGUIDs){
Item item = _itemDB.GetItem(id);
items.Add(item);
}
Character character = new Character(newCharacterSO.Portrait, newCharacterSO.AttributeSheet, newCharacterSO.InventoryCapacity, items);
_charactersDict.Add(newCharacterSO.ID, character);
}
}
}
private bool ValidateData(CharacterSO characterSO){
bool isValid = true;
foreach (string id in characterSO.StartingItemGUIDs){
isValid = _itemDB.ItemsDict.ContainsKey(id);
if (!isValid){
isValid = false;
break;
}
}
return isValid;
}
public Character GetCharacter(string id){ // Issue here???
if (_charactersDict.ContainsKey(id)){
Character character = new Character(_charactersDict[id].PortraitSprite, _charactersDict[id].AttributeSheet, _charactersDict[id].InventoryCapacity, _charactersDict[id].Items);
return character;
}
else{
return null;
}
}
[ContextMenu("Print DB Contents")]
private void PrintDBContents(){
foreach (var entry in _charactersDict){
Debug.Log($"{entry.Key}, {entry.Value.AttributeSheet.Name}");
}
}
}
CharacterPrefab
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterPrefab : MonoBehaviour
{
[SerializeField] private string _name;
[SerializeField] private string _characterTemplateID;
[SerializeField] private Alignment _alignment;
private Character _character;
private CharacterDB _characterDB;
public Character Character { get { return _character; } }
private void Start(){
InitializeCharacter(_alignment);
}
public void InitializeCharacter(Alignment alignment){
_characterDB = FindObjectOfType<CharacterDB>();
if (_characterDB == null){
Debug.Log("Cannot find CharacterDB");
}
_character = _characterDB.GetCharacter(_characterTemplateID);
// Set character alignment
if (_alignment == Alignment.Player){
_character.CombatantType = Alignment.Player;
}
else if (_alignment == Alignment.Enemy){
_character.CombatantType = Alignment.Enemy;
}
// Initialize health
_character.Health = _character.AttributeSheet.MaxHP;
// Set in-game name
if (_name != null){
_character.Name = _name;
}
this.name = $"{_character.CombatantType}: {_character.Name}";
}
[ContextMenu("Debug Character")]
private void DebugCharacter(){
foreach (Item item in this.Character.Items){
if (this.Character.Items.Count <= 0){
Debug.Log($"{this} has no Items.");
}
else{
Debug.Log($"Character prefab {this} has in Items: {item.ItemName} which isEquipped: {item.IsEquipped}");
}
}
}
}