RPG Character Creator & Modular Armor Tutorial

There’s a lot to unpack here, but…

The SavingWrapper should only only be in the PersistentObjectsPrefab… don’t add it anywhere else. The POP should be loaded when the Main Menu loads (i.e. when the game starts).

and the characterGenerator does not go on the player in the main game, right? I figured that it might go because… well… there was a RestoreState() function :sweat_smile: (dumb choice I know, but I mainly learn by trying and failing)

The charactergenerator is on all versions of the player, in the main menu, the customize scene, and in the game.

May as well put it on the prefab at this point in time… Somehow though, the save still does not work when we transition between saves (Edit: Still testing it, and… Nope, it’s not working)

It should be on the prefab, absolutely
And make sure that the JsonSaveableEntity/SaveableEntity in all scenes and the prefab has the id set to Player

OK umm, on the fly. If we remove the saving wrapper from the parent of the confirm button, how do we confirm our character choice and take it to the main game level? (It was my only temporary option for now)

Create a new class with a public method that does FindObjectOfType to get the SavingWrapper and calls the function.

OK I’ll try this in a bit (deleting the addon script off my player accidentally reset all my buttons, fixing that as we speak). Should this fix the weapon equipment issue as well, or do I have to recreate all my weapons as Synty Equipable Items now as well?

Weapons don’t get changed. They are just the old weaponconfigs. Weapons are static meshes, and can be instantiated through the existing course system.

Because right now I have a lot of questions coming from this:

  1. My character doesn’t get saved into the real game for some reason. I checked the JSON entity, both have it, and both are with the same unique ID of ‘player’. Instead, my game resets my character to the default settings of ‘CharacterGenerator.cs’ (my guess is because of the ‘LoadDefaultCharacter()’ in “Start()”)

  2. My enemies deal damage, but I can’t. My game only lets me accept damage now

  3. The UI of my player equipment system doesn’t display what I wield anymore…

  4. Unless I drag and drop, my game doesn’t allow me to wield weapons anymore, through the ‘TryHandleRightClick()’ method we developed (and believe me when I say this, I am surprised). And when I drag and drop them, like I mentioned in 3, they aren’t visible in the equipment tab

These issues weren’t there before. I apologize again if I’m taking so much of your time tonight (and these are all just the bugs I found so far)

That sounds like you may not be Saving before switching from the character generation scene to the main menu scene.

None of these things should have been affected by anything we did here…
Undo any changes (I have convinced you to use source control, right? right?) you made to:

  • WeaponConfig.cs
  • StatsEquipment.cs
  • Equipment.cs
  • Fighter.cs
    None of these things need to be modified in the slightest for the CharacterGenerator. The CharacterGenerator should actually stand on it’s own 2 feet by simply being on the Player with no other changes.

I have literally done absolutely no changes to any of these scripts when coding the Character Generator… (my source control, for the time being, is a funny one. It’s, ahem, Unity Packages (usually after every major system change. When the winter break arrives I’ll get the git course and work on it))

Mine doesn’t flow this way. It goes from the Character Generator to the game scene, I don’t understand why should I go back to the main menu scene first tbh

Anyway, this is the script I tried writing to go from the character customizer to the main game:

using System.Collections;
using System.Collections.Generic;
using RPG.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

public class CharacterGenToGame : MonoBehaviour
{

    private SavingWrapper savingWrapper;

    [SerializeField] float fadeOutTime;
    [SerializeField] int mainLevelBuildIndex = 2;
    [SerializeField] float fadeInTime;

    private void Awake() {
        savingWrapper = FindObjectOfType<SavingWrapper>();
    }

    public void ContinueToMainLevel()
    {
        // Transitioning to the main game scene:
        // savingWrapper.Save();
        StartCoroutine(LoadMainGameScene());
    }

    private IEnumerator LoadMainGameScene()
    {

        Fader fader = FindObjectOfType<Fader>();
        yield return fader.FadeOut(fadeOutTime);
        SceneManager.LoadScene(mainLevelBuildIndex);
        yield return fader.FadeIn(fadeInTime);

    }

}

It works absolutely fine for transitioning from the character generator scene to the game world, but it does not do any sort of saving… Please let me know how I can fix it, to get the save to work properly, because the commented out saving system of mine just does not allow the confirm button to work

Edit: OK so after fixing a few bugs (and still trying), I currently have two issues:

  1. The weapons no longer instantiate in my hand. My game works as if they exist in the players’ hand, but visibility-wise, the weapons are literally turned off. I need help with that (I went to the depths of the weapon position in the players’ hand when it’s there, and the mesh renderer says it’s active… apparently it’s not visible in the players’ hand though, and the same goes for the shield (which is something I frankly never addressed before, so we can put that on the side for now)).

For testing purposes, I brought my old character (his avatar and hand transform values for ‘Fighter.cs’ script) back to the scene, and this issue didn’t exist, then I did an extremely stupid test of having both characters visible in my scene under each other, and… yup, the bow is somehow only attracted to my old player characters’ hands for some reason. Not the avatar, it’s specifically attracted to the hands, and I have absolutely no idea why (as in why it’s not working with the modular characters, but with the old ones…).

  1. The saving system is not working, still… I’m using your JSON System, but it still only instantiates the default values of my ‘CharacterGenerator.cs’ script… Can you please help me fix this? The script above failed me :confused: (After a bit of further investigation, I discovered something new. If you go to the main menu from your new scene and reload your save, you’ll get a different specific character from whatever you initially had for some reason. He’s neither what the default character generators have, nor what you initially set up, and it’s baffling me)

I maxed out on my edits, but here’s an update of my first problem above:

  1. The weapons are literally only attracted to my old player models’ hands. Not his avatar, only his hands. I did a bunch of tests and that’s what I reached… that for my weapons to render in the scene and be visible to the player, we need the old player model to be visible, and his hands attached to the ‘Fighter.cs’ variables that seek those hands… which is troubling me

Edit: 21 hours later… still, no improvements. All I managed to figure out so far, was where to add the save and load values, but I still need help

Here is my “new” CharacterGenToGame.cs:

using System.Collections;
using RPG.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

public class CharacterGenToGame : MonoBehaviour
{

    private SavingWrapper savingWrapper;

    [SerializeField] float fadeOutTime;
    [SerializeField] int sceneToLoad = 2;
    [SerializeField] float fadeInTime;

    private void Awake() {
        savingWrapper = FindObjectOfType<SavingWrapper>();
        }

    public void ContinueToMainLevel()
    {
        // Transitioning to the main game scene:
        StartCoroutine(LoadMainGameScene());
    }

    private IEnumerator LoadMainGameScene()
    {
        Fader fader = FindObjectOfType<Fader>();
        yield return fader.FadeOut(fadeOutTime);
        savingWrapper.Save();
        SceneManager.LoadScene(sceneToLoad);
        savingWrapper.Load();
        yield return fader.FadeIn(fadeInTime);
    }

}

Still failed though, and I really… REALLY… REALLY need help

Hey guys, any updates about this? I tried solving it on my own the entire weekend, I tried every trick in the book, but nothing worked.

Whether it flows from the character creation scene to the game scene or the menu scene, the data still must be saved.

While that may be true, the issues of the player not accepting damage while the enemies can has zero to do with the character generator. The Character Generator should only be affecting how the character looks, not anything whatsoever to do with actual gameplay.

You um… never saved here… And you never restored…
In fact you’re only storing the SavingWrapper, not doing anything with it like… say…

savingWrapper.Save();

or

savingWrapper.Load();

You have encountered the Synty Scaling Bug! Congratulations!
This is an issue that Synty has between their scaling of models… some models are scaled correctly, other models are… not at all…

Here’s what you need to do:
In the PolygonModularFantasyHero, find your right and left hand transforms.
Create empty GameObjects under these transforms, and give them clever names like “RightHandTransform” and “LeftHandTransform”
Set the scaling on these empty GameObjects to 100,100,100
Assign these new transforms as your Right and Left hand transforms.

You also may want to start that LoadMainGameScene() with DontDestroyOnLoad(gameObject); and end it with Destroy(gameObject)';
Additionally, you’ll want to make sure that this GameObject that the script is running on is in the root much like the Portal.

Sorry, I took part of the weekend off to celebrate another successful trip around the sun. I do this around this time every year.

2 Likes

Hey Brian, thanks for taking the time to respond to me, I hope your weekend trip was a great one :laughing: - regarding this though, my confirm button was not in the root (like portal)… it was in the UI Canvas (and believe me I never would’ve figured this one out on my own), but trying to place it in the root means it won’t show up on the UI Canvas… how do we go around this? Do we place the script on the UI Canvas itself and deactivate it in the main game scene?

Place an empty GameObject in the scene with your code to save and transition.
Your button to confirm should call this GameObject’s CharacterGenToGame.ContinueToMainLevel()

1 Like

Yup, I did that now as well. The teleporter is on my hierarchy root now, as you can see here:

and my Confirm button is still in the UI Canvas (the ‘confirm button’, the last element in ‘UI Canvas’)

I also updated my code to contain the Destroy and DontDestroyOnLoad(), making my “CharacterGenToGame.cs” script look like this:

using System.Collections;
using RPG.Inventories;
using RPG.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

public class CharacterGenToGame : MonoBehaviour
{

    private SavingWrapper savingWrapper;
    private CharacterGenerator characterGenerator;

    [SerializeField] float fadeOutTime;
    [SerializeField] int sceneToLoad = 2;
    [SerializeField] float fadeInTime;

    private void Awake() {
        savingWrapper = FindObjectOfType<SavingWrapper>();
        characterGenerator = FindObjectOfType<CharacterGenerator>();
        }

    public void ContinueToMainLevel()
    {
        // Transitioning to the main game scene:
        StartCoroutine(LoadMainGameScene());
        
    }

    private IEnumerator LoadMainGameScene()
    {
        /* Fader fader = FindObjectOfType<Fader>();
        DontDestroyOnLoad(characterGenerator);
        yield return fader.FadeOut(fadeOutTime);
        savingWrapper.Save();
        yield return SceneManager.LoadSceneAsync(sceneToLoad);
        savingWrapper.Load();
        yield return fader.FadeIn(fadeInTime);
        savingWrapper.Save();
        Destroy(gameObject); */

        if (sceneToLoad < 0) yield break;
        DontDestroyOnLoad(gameObject);
        Fader fader = FindObjectOfType<Fader>();
        // DontDestroyOnLoad(characterGenerator);
        yield return fader.FadeOut(fadeOutTime);
        savingWrapper.Save();
        // yield return SceneManager.LoadSceneAsync(sceneToLoad);
        SceneManager.LoadScene(sceneToLoad);
        savingWrapper.Load();
        yield return fader.FadeIn(fadeInTime);
        Destroy(gameObject);
    }

}

I attached this script to my ‘Main Level Teleporter’ (It is the empty gameObject that calls the ‘confirm’ button), and it called the OnClick() function (on the button, which is still on the UI Canvas) event assigned by Unity to utilize ‘LoadMainGameScene()’ through ‘public void ContinueToMainLevel()’. I was trying to follow the ‘Portal.cs’ script, BUT… the save and load still did not work. Any alternative solutions?

As for this issue, your solution fixed it. Thank you Brian, but… I still don’t understand, what exactly have we done here that was different that fixed it? Did they accidentally downscale their hand transforms by accident or something…? (I’m guessing when I switch to Blink down the line, I’ll be doing a lot of fixing there as well…)

Any particular reason you changed this? It was correct as yield return SceneManager.LoadSceneAsync(sceneToLoad);

I’m not entirely sure the details, just the symptoms of the bug. With certain Synty characters, you have to play the scale game.

Well… if it ain’t a blacked out screen, it’s probably something like this (a missing game world). This is what the asynchronous loader returns… (it messed up the spawn point coordinates. The world is just behind the player right now. Not gone, just behind him)

This is the code that returns this issue (and the saving system still didn’t work):

private IEnumerator LoadMainGameScene()
    {
        if (sceneToLoad < 0) yield break;
        DontDestroyOnLoad(gameObject);
        Fader fader = FindObjectOfType<Fader>();
        yield return fader.FadeOut(fadeOutTime);
        savingWrapper.Save();
        yield return SceneManager.LoadSceneAsync(sceneToLoad);
        savingWrapper.Load();
        yield return fader.FadeIn(fadeInTime);
        Destroy(gameObject);
    }

At one point it was working fine, and the next… not anymore (and I have no idea why)

Privacy & Terms