Hiya! I'm using a Unity sprite library to dynamically manage sprites, such as the weapons on a character. For each weapon, I set up an Equip Schematic in the Schematic Settings. In this schematic, I utilize a Call Function Node to activate a Method that updates the string to match the current weapon. This Method also updates a global variable, helping the system recognize the equipped weapon, which is useful when loading a game for example.

However, I'm encountering an issue during battles. When the character gets hit by an opponent, the global variable reverts to its default value, causing the sprite to change incorrectly. In the editor, the character still appears to be equipped with the correct weapon. Yet, when I check the global variables, they display incorrectly. If I switch weapons through the battle menu during gameplay, the global variable corrects itself, updating the sprite accordingly. After this change, the problem doesn't recur even if the character gets hit again.

I've thoroughly checked the code but can't seem to pinpoint the cause of this issue. The function to swap the weapon and global variable is only used by the Equip Schematic.

Any suggestions would be great! Thank you in advance!
  • I conducted additional tests using the same setup for another character, where I applied the same code and sprite library configuration but changed only the variable names. Interestingly, the issue continues to occur with the first character but never with the second. I'm struggling to pinpoint the cause of this problem
  • edited July 2024
    The swap method, which I trigger through a Call Function node in the weapon Equip schematic, is the one I use.

    using System.Collections;
    using System.Collections.Generic;
    using Unity.Collections;
    using UnityEngine;
    using UnityEngine.ProBuilder.Shapes;
    using UnityEngine.U2D;
    using UnityEngine.U2D.Animation;
    using GamingIsLove.ORKFramework;
    using GamingIsLove.Makinom;
    using GamingIsLove.Makinom.Components;

    public class WeaponSwapper : MonoBehaviour
    {
    public static string ArisCurrentWeapon; // Static variable to hold the current weapon label

    [SerializeField]
    private SpriteLibrary spriteLibrary = default;

    [SerializeField]
    private SpriteResolver targetResolver = default;

    [SerializeField]
    private string targetCategory = default;

    void Start()
    {
    InitializeWeapon();
    }

    public void Swap(string spriteLabel)
    {
    // Fetch sprite using label
    UnityEngine.Sprite customSprite = spriteLibrary.GetSprite(targetCategory, spriteLabel);

    if (customSprite == null)
    {
    Debug.LogError($"Sprite with label '{spriteLabel}' not found in category '{targetCategory}'.");
    return;
    }

    // Duplicate bones and poses from a reference sprite
    string referenceLabel = targetResolver.GetLabel();
    UnityEngine.Sprite referenceSprite = spriteLibrary.GetSprite(targetCategory, referenceLabel);
    if (referenceSprite != null)
    {
    SpriteBone[] bones = referenceSprite.GetBones();
    NativeArray poses = referenceSprite.GetBindPoses();
    customSprite.SetBones(bones);
    customSprite.SetBindPoses(poses);
    }
    else
    {
    Debug.LogError($"Reference sprite with label '{referenceLabel}' not found in category '{targetCategory}'.");
    return;
    }

    // Inject new sprite
    spriteLibrary.AddOverride(customSprite, targetCategory, spriteLabel);
    targetResolver.SetCategoryAndLabel(targetCategory, spriteLabel);

    // Set the global variable after successful swap
    SetGlobalVariable(spriteLabel);

    Debug.Log($"Swapped to sprite: '{spriteLabel}' in category: '{targetCategory}'.");
    }

    public void SetGlobalVariable(string arisCurrentWeapon)
    {
    // Use Makinom to set a global variable
    Maki.Game.Variables.Set("ArisCurrentWeapon", arisCurrentWeapon);
    Debug.Log($"Set global variable 'ArisCurrentWeapon' to '{arisCurrentWeapon}'");
    // Update the static variable
    ArisCurrentWeapon = arisCurrentWeapon;
    Debug.Log($"Updated static variable 'ArisCurrentWeapon' to '{ArisCurrentWeapon}'");
    }

    public void InitializeWeapon()
    {
    string currentWeaponLabel = Maki.Game.Variables.GetString("ArisCurrentWeapon");
    if (!string.IsNullOrEmpty(currentWeaponLabel))
    {
    Swap(currentWeaponLabel);
    }
    else
    {
    Debug.Log("No weapon currently set in global variables.");
    }
    }
    }

    Post edited by Anoo on
  • Using a static field in your component will have the same value in all instances of the component, e.g. having the component on multiple combatants (e.g. player and enemy) could have the wrong value for the one that was initialized first (basically it's wrong for everyone except the latest change).

    As for ORK/Makinom variables - they can't change or reset on their own. There has to be somewhere that's doing it, e.g. a schematic or script accessing it and doing the change.
    Please consider rating/reviewing my products on the Asset Store (hopefully positively), as that helps tremendously with getting found.
    If you're enjoying my products, updates and support, please consider supporting me on patreon.com!
  • For testing purposes, I added a new script to the second combatant. It uses essentially the same code as before but with all variables and components renamed to ensure they're separate from each other. However, the problem still persists.
  • edited July 2024
    Well, I've identified the problem, although I'm still unsure why it's occurring. The issue stems from the "Add to Bestiary" node at the end of the attack schematic. If I remove it, it all works perfectly.

    I created a new schematic for it and ran it following the attack schematic, but as soon as this runs, the global variable for the weapon swapper resets.

    this is the console log of the moment the sprite unintentionally switched back (with the Add to Bestiary node):
    Swapped to sprite: 'Entry' in category: 'Sword'.
    UnityEngine.Debug:Log (object)
    WeaponSwapper:Swap (string) (at Assets/WeaponSwapper.cs:64)
    System.Reflection.MethodBase:Invoke (object,object[])
    GamingIsLove.Makinom.Reflection.SchematicCallFunction:Call (object,GamingIsLove.Makinom.Schematics.Schematic,bool)
    GamingIsLove.Makinom.Schematics.Nodes.CallFunctionNode/Runtime:Continue ()
    GamingIsLove.Makinom.Schematics.Nodes.CallFunctionNode:Execute (GamingIsLove.Makinom.Schematics.Schematic)
    GamingIsLove.Makinom.Schematics.Schematic:ExecuteNextNode ()
    GamingIsLove.Makinom.Schematics.Schematic:Start ()
    GamingIsLove.Makinom.Schematics.Schematic:PlaySchematic (object,GamingIsLove.Makinom.Schematics.ISchematicStarter,object,object,bool,GamingIsLove.Makinom.MachineUpdateType,int)
    GamingIsLove.Makinom.Schematics.Schematic:Play (GamingIsLove.Makinom.MakinomSchematicAsset,object,GamingIsLove.Makinom.Schematics.ISchematicStarter,object,object,bool,GamingIsLove.Makinom.VariableHandler,GamingIsLove.Makinom.SelectedDataHandler)
    GamingIsLove.ORKFramework.EquipShortcut:Equipped (GamingIsLove.ORKFramework.Combatant)
    GamingIsLove.ORKFramework.Combatants.CombatantEquipment:Equip (GamingIsLove.ORKFramework.EquipmentSlotSetting,GamingIsLove.ORKFramework.EquipShortcut,GamingIsLove.ORKFramework.Combatant,GamingIsLove.ORKFramework.Combatant,bool)
    GamingIsLove.ORKFramework.CombatantAccessHandler:Equip (GamingIsLove.ORKFramework.Combatant,GamingIsLove.ORKFramework.EquipmentSlotSetting,GamingIsLove.ORKFramework.EquipShortcut,GamingIsLove.ORKFramework.Combatant,GamingIsLove.ORKFramework.Combatant,bool)
    GamingIsLove.ORKFramework.Combatants.CombatantEquipment:EquipAccess (GamingIsLove.ORKFramework.EquipmentSlotSetting,GamingIsLove.ORKFramework.EquipShortcut,GamingIsLove.ORKFramework.Combatant,GamingIsLove.ORKFramework.Combatant,bool)
    GamingIsLove.ORKFramework.StartEquipment:EquipOn (GamingIsLove.ORKFramework.Combatant)
    GamingIsLove.ORKFramework.Combatant:Init (int,int,GamingIsLove.ORKFramework.Class,bool,bool,bool,bool,bool,bool)
    GamingIsLove.ORKFramework.BestiaryEntry:GetCombatant ()
    GamingIsLove.ORKFramework.BestiaryHandler:AddNew (string)
    GamingIsLove.ORKFramework.BestiaryHandler:SetComplete (string,System.Collections.Generic.List1)
    GamingIsLove.ORKFramework.BestiaryHandler:SetComplete (GamingIsLove.ORKFramework.Combatant,System.Collections.Generic.List1,bool,bool)
    GamingIsLove.ORKFramework.Schematics.Nodes.AddToBestiaryNode:Execute (GamingIsLove.Makinom.Schematics.Schematic)
    GamingIsLove.Makinom.Schematics.Schematic:ExecuteNextNode ()
    GamingIsLove.Makinom.Schematics.Schematic:Start ()
    GamingIsLove.Makinom.Schematics.Schematic:PlaySchematic (object,GamingIsLove.Makinom.Schematics.ISchematicStarter,object,object,bool,GamingIsLove.Makinom.MachineUpdateType,int)
    GamingIsLove.ORKFramework.BaseAction:PlayNextSchematic ()
    GamingIsLove.ORKFramework.BaseAction:SchematicFinished (GamingIsLove.Makinom.Schematics.Schematic)
    GamingIsLove.Makinom.Schematics.Schematic:EndSetup ()
    GamingIsLove.ORKFramework.Schematics.BattleActionSchematic:EndSetup ()
    GamingIsLove.Makinom.Schematics.Schematic:EndSchematic ()
    GamingIsLove.Makinom.Schematics.Schematic:ExecuteNextNode ()
    GamingIsLove.Makinom.Schematics.Schematic:NodeFinished (int)
    GamingIsLove.Makinom.Schematics.Nodes.ChangeFieldsNode/Runtime:Continue ()
    GamingIsLove.Makinom.Schematics.Nodes.ChangeFieldsNode/Runtime:Continue ()
    GamingIsLove.Makinom.Schematics.Nodes.ChangeFieldsNode:Execute (GamingIsLove.Makinom.Schematics.Schematic)
    GamingIsLove.Makinom.Schematics.Schematic:ExecuteNextNode ()
    GamingIsLove.Makinom.Schematics.Schematic:NodeFinished (int)
    GamingIsLove.Makinom.Schematics.Nodes.SearchObjectsNode:Execute (GamingIsLove.Makinom.Schematics.Schematic)
    GamingIsLove.Makinom.Schematics.Schematic:ExecuteNextNode ()
    GamingIsLove.Makinom.Schematics.Schematic:Start ()
    GamingIsLove.Makinom.Schematics.Schematic:PlaySchematic (object,GamingIsLove.Makinom.Schematics.ISchematicStarter,object,object,bool,GamingIsLove.Makinom.MachineUpdateType,int)
    GamingIsLove.ORKFramework.BaseAction:PlayNextSchematic ()
    GamingIsLove.ORKFramework.BaseAction:SchematicFinished (GamingIsLove.Makinom.Schematics.Schematic)
    GamingIsLove.Makinom.Schematics.Schematic:EndSetup ()
    GamingIsLove.ORKFramework.Schematics.BattleActionSchematic:EndSetup ()
    GamingIsLove.Makinom.Schematics.Schematic:EndSchematic ()
    GamingIsLove.Makinom.Schematics.Schematic:ExecuteNextNode ()
    GamingIsLove.Makinom.Schematics.Schematic:NodeFinished (int)
    GamingIsLove.Makinom.Schematics.Node
    Post edited by Anoo on
  • Well, the bestiary creates a new instance of that combatant for displaying information. Based on the console log the combatant equips something, which causes the schematic to start, calling your code and changing the static field of your class.

    So, as said earlier - the static field in your class will be an issue if multiple combatants use this.
    Why is this a static field and what is it used for further?
    Please consider rating/reviewing my products on the Asset Store (hopefully positively), as that helps tremendously with getting found.
    If you're enjoying my products, updates and support, please consider supporting me on patreon.com!
Sign In or Register to comment.