[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}
andB.{c,c,c}
thec,c
fromA
can move to another holder if in another holder have a same of object in this case isc
but the next of holder cant be full, if there is full the remainig is stay on current holder for exampleA.{a,b,c,c}
andB.{c,c,c,c}
so the A and B only can movec
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]