Hi everyone!
I’m currently working on a little project focused on in-game photography, roughly comparable to the photo features from Beyond Good and Evil or Sly Cooper. I’m still at the very beginning, designing the way I bundle motifes into different photo albums. To reward the player some payment in game, I’d like to assign each motif a value that’s paid when the players takes a photo of this motif for the very first time. Additionally, the players recieves a bonus payment for completing a photo album.
Now, for setting up those albums I thought it might be a good idea to use reflection to ensure that every motif is part of the correct album. I’d like to do that by using a ScriptableObject and selecting the topic of the album. Using reflection, the ScriptableObject then automatically populates a collection with all corresponding motifes belonging to that topic so I’m neither missing any nor using them multiple times. Then, I could assign the reward for each motif and the bonus reward for completing the album.
Example:
This is an (incomplete) overview of how I’m currently structuring my motifes.
Now, if I create a new album, I’d like to select Dogs from a dropdown menu of possible topics. The corresponding collections is then populated with all subclasses of dogs - in this case, Dalmation and Dachshund. The list of possible topics is supposed to be the last layer of abstract classes, so the 3rd layer (currently consisting of Bears, Dogs, and Insects).
Unfortunately, I don’t know how to do that and so far didn’t find anything online that showed me I could achieve that. My ScriptableObject script currently looks like this:
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
[CreateAssetMenu(fileName = "New PhotoCollection", menuName = "ScriptableObjects/PhotoCollection")]
public class PhotoCollection : ScriptableObject
{
[SerializeField]
private Motif motif;
// this is a serializable dictionary that enables
// editing the rewards in the editor
[SerializeField]
private MotifRewardDictionary collection;
[SerializeField]
private int completionReward;
#if UNITY_EDITOR
public void OnValidate()
{
if (motif == null)
return;
//
var myTypes = Assembly.GetAssembly(typeof(Motif)).GetTypes().Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(motif.GetType()));
// TODO populate collection
foreach (KeyValuePair<Motif, PhotoReward> pair in collection)
{
if (pair.Value.Amount == 0)
{
Debug.LogWarning("Reward for " + pair.Key + " is 0.");
}
}
if (completionReward == 0)
{
Debug.LogWarning("CompletionReward is 0.");
}
}
#endif
public void AddPhotoToCollection (Motif motif)
{
// the photo doesn't involve a motif that we want for this collection
if (!collection.ContainsKey(motif))
return;
// a photo with this motif was already added to this collection
if (collection[motif].IsCollected == true)
return;
collection[motif].IsCollected = true;
// TODO trigger payment event
if (IsComplete())
{
// TODO trigger payment event
}
}
private bool IsComplete()
{
foreach (var value in collection.Values)
{
if (value.IsCollected == false)
{
return false;
}
}
return true;
}
}
Can anyone point me into the right direction here?
Thank you in advance!
//Edit: Obviously, some things like !myType.IsAbstract
are completely wrong but I tried displaying some concrete subclasses (dachshund, etc) first, but couldn’t even manage to do that - let alone display abstract classes.