Home Game Development unity – Trying to implement undo system

unity – Trying to implement undo system

0
unity – Trying to implement undo system

[ad_1]

I’ve got a problem with my undo system that ive made, the idea is I want to make a sort puzzle game like this => https://www.youtube.com/watch?v=VdXi9UQhOng

WHAT I UNDERSTAND

  • There is some movement when click the holder to another holder, the movement is also based on contigues of the object, for example A.{a,b,c,c} and B.{c,c,c} the c,c from A can move to another holder if in another holder have a same of object in this case is c but the next of holder cant be full, if there is full the remainig is stay on current holder for example A.{a,b,c,c} and B.{c,c,c,c} so the A and B only can move c once, either A to B vice verca.
  • Undo System that I think almost same like movement but when click the button instead of click the holder.

Thats for the mechanics from the game that i understand so far.

WHAT IM DOING SO FAR

So I implement all of that inside script down below

Move Up: This when the holder i click then its select the contigues objects and store it to frontObjects List

 public void MoveObjectsUp(float distance)
 {
     frontObjects.Clear();

     for (int i = objects.Count - 1; i >= 0; i--)
     {
         var obj = objects[i];

         if (obj != null && (frontObjects.Count == 0 || obj.ObjectGroupId == frontObjects[0].ObjectGroupId))
         {
             frontObjects.Insert(0, obj);  // Insert at the beginning of the list
         }
         else
         {
             break; // Stop when a different ObjectGroupId is encountered
         }
     }

     foreach (var obj in frontObjects)
     {
         if (obj != null)
         {
             obj.ActivateHighlight();

             Move(obj, distance);
         }
     }

     IsPending = true;
 }

Move Down: This when the holder i click again after Move Up it’s like a toggle, also clearing the frontObjects from list

 public void MoveBack(float distance)
 {
     foreach (var obj in frontObjects)
     {
         if (obj != null)
         {
             obj.DeadActivateHighlight();

             Move(obj, -distance);
         }
     }

     frontObjects.Clear();

     IsPending = false;
 }

MoveToHolder: move the current object to next holder, there is objects list to store objects into a list and backObject list to store the undo objects into a list, and unmovedObjects list to store remaining objects that doesnt move

 public void MoveToHolder(List<Object> objs)
 {
     if (IsPending)
     {
         IsPending = false;
     }

     int objectsToAdd = Mathf.Min(objs.Count, maxObject - objects.Count);
     int totalObject = objects.Count + objs.Count;

     Debug.Log($"Object to add:{objectsToAdd}, current list count: {objects.Count}, total object: {totalObject}");

     for (int i = 0; i < objs.Count; i++)
     {
         if (objects.Count < maxObject)
         {
             objects.Add(objs[i]);

             if (!backObjects.Contains(objs[i]))
             {
                 backObjects.Add(objs[i]);
             }

             objs[i].Move(GetObjectPosition(objects.Count - 1));
         }
         else
         {
             unmovedObjects.Add(objs[i]);
         }

     }
 }

UnMoveListThenRemove: this is for clear the current unmoved list after move to next holder

 public void UnmoveListThenRemove(Holder fromHolder, Holder toHolder)
 {
     if (fromHolder.unmovedObjects.Count > 0)
     {
         foreach (var obj in fromHolder.unmovedObjects)
         {
             toHolder.objects.Add(obj);
         }

         fromHolder.unmovedObjects.Clear();

         // Move the Object again
         for (var i = 0; i < toHolder.objects.Count; i++)
         {
             toHolder.objects[i].transform.SetParent(toHolder.contentParent.transform);

             toHolder.objects[i].transform.position = GetObjectPosition(i);
         }
     }
 }

RemoveFromList: this is for clear the objects list after MoveToHolder

 public void RemoveFromList()
 {
     objects.RemoveAll(obj => frontObjects.Contains(obj));

     // Clear Frontobject
     foreach (var obj in frontObjects)
     {
         if (obj != null)
         {
             obj.DeadActivateHighlight();
         }
     }

     frontObjects.Clear();

     IsPending = false;
 }

Remove Undo: this is for clear the backObjects list, usually used after undo

 public void RemoveUndo()
 {
     objects.RemoveAll(obj => backObjects.Contains(obj));

     // Clear BackObjects
     foreach (var obj in backObjects)
     {
         if (obj != null)
         {
             obj.DeadActivateHighlight();
         }
     }

     backObjects.Clear();

     IsPending = false;
 }

In this script is how that I called from holder script

public struct MoveData
{
   public Holder FromHolder { get; set; }
    public Holder ToHolder { get; set; }
    public List<Object> ObjectsData { get; set; }
}
public class LevelManager : MonoBehaviour
{
  private List<Holder> _holders = new List<Holder>();
  public Stack<MoveData> _undoStack = new Stack<MoveData>();
    

 public void OnClickUndo()
 {
     // Problem here
     if (CurrentState != State.Playing || _undoStack.Count <= 0)
         return;

     var moveData = _undoStack.Pop();
     MoveObjectUndo(moveData.ToHolder, moveData.FromHolder);
 }

 private void Update()
 {
     if (CurrentState != State.Playing)
         return;

     // For Click on Holder
     if (Input.GetMouseButtonDown(0))
     {
         var collider = Physics2D.OverlapPoint(_camera.ScreenToWorldPoint(Input.mousePosition));
         if (collider != null)
         {
             var holder = collider.GetComponent<Holder>();

             if (holder != null)
                 OnClickHolder(holder);
         }
     }
 }
private void OnClickHolder(Holder holder)
{
    //Debug.Log("Clicked " + holder.gameObject.name);

    var pendingHolder = _holders.FirstOrDefault(h => h.IsPending);

    if (pendingHolder != null && pendingHolder != holder)
    {
        if (holder.objects.Count == 0)
        {
            MoveObjectsFromOneToAnother(pendingHolder, holder);
        }
        else
        {


            for (int i = 0; i < pendingHolder.frontObjects.Count; i++)
            {
                List<Object> movedObjects = new List<Object>(pendingHolder.backObjects);

                if (pendingHolder.frontObjects.All(frontObj =>
                holder.objects.Any(holderObj =>
                frontObj.ObjectGroupId == holderObj.ObjectGroupId &&
                frontObj.ObjectGroupId == holder.objects.Last().ObjectGroupId)) && !holder.IsFull)
                {
                    // Problem here
                    _undoStack.Push(new MoveData
                    {
                        FromHolder = pendingHolder,
                        ToHolder = holder,
                        ObjectsData = movedObjects
                    });

                    MoveObjectsFromOneToAnother(pendingHolder, holder);

                }
                else
                {
                    holder.IsPending = true;
                    pendingHolder.IsPending = false;
                }
            }
        }

        // Like Switch
        if (pendingHolder != null && !pendingHolder.frontObjects.All(frontObj =>
                holder.objects.Any(holderObj =>
                frontObj.ObjectGroupId == holderObj.ObjectGroupId &&
                frontObj.ObjectGroupId == holder.objects.Last().ObjectGroupId)))
        {
            pendingHolder.MoveBack(.2f);

            holder.MoveObjectsUp(.2f);
        }
    }
    else
    {
        if (holder.objects.Any())
        {
            holder.IsPending = !holder.IsPending;
        }

        if (holder.IsPending)
        {
            holder.MoveObjectsUp(.2f);
        }
        else
        {
            holder.MoveBack(.2f);
        }
    }
}

private void MoveObjectsFromOneToAnother(Holder fromHolder, Holder toHolder)
{
    previousHolder = fromHolder;

    // Move the object
    toHolder.MoveToHolder(fromHolder.frontObjects);

    //Move To its Parent
    toHolder.MoveGameObjectToItsParent();

    //Remove the list
    fromHolder.RemoveFromList();

    fromHolder.UnmoveListThenRemove(toHolder, fromHolder);
}

private void MoveObjectUndo(Holder fromHolder, Holder toHolder)
{
    // Move the object
    toHolder.MoveToHolderUndo(fromHolder.backObjects);

    //Move To its Parent
    toHolder.MoveGameObjectToItsParent();

    ////Remove the list
    fromHolder.RemoveUndo();

    //toHolder.ClearPreviousObject();

    //fromHolder.UnmoveListThenRemove(toHolder, fromHolder);
}
}

ISSUE

So i think all working but it has bug in the undo system for now.

the issue is when I click the undo its working only on the 1 object or 2 contigues objects, when object more that that inflict bug like the all of objects move to previous holder, sometimes when I move the object to the empty holder I cant undo the object so object stay on that holder, also some times move the other index

  • When move to empty Holder (bug)

  • Other Index that move (bug)


 

  • More of 2 contigues objects move all of them to previous holder (bug)

Am i missing something here?

[ad_2]

Previous article Both models of Apple Pencil are discounted for Black Friday
Next article Lies Of P’s New Update Actually Gives You A Fighting Chance
Hello there! My name is YoleeTeam, and I am thrilled to welcome you to AmazonianGames.com. As the premier destination for all things related to Amazon Games' universe, we are dedicated to providing you with the most exciting and immersive gaming experiences out there. From captivating visuals to exhilarating gameplay, our website is packed with comprehensive insights, updates, and reviews to keep you ahead of the game. Whether you're a seasoned gamer or new to the scene, I am here to guide you through this virtual frontier. If you have any questions or suggestions, feel free to reach out to me at john@yoleesolutions.com. Embark on your Amazon gaming journey today with AmazonianGames.com and let the adventure begin!