Unity/3Match
[Unity] 3) Input / 블럭 Swap
GiveZero
2023. 2. 19. 22:11
유니티에는 다음과 같이 Event Trigger이 존재하는데, 컴포넌트로 사용하지않고
스크립트 내에서 설정할 것이다.
BlockController.cs
void InitEventTrigger()
{
EventTrigger eventTrigger = transform.GetComponent<EventTrigger>();
EventTrigger.Entry pointerDown = new EventTrigger.Entry();
pointerDown.eventID = EventTriggerType.PointerDown;
pointerDown.callback.AddListener((data) => { OnPointerDown((PointerEventData)data); });
eventTrigger.triggers.Add(pointerDown);
EventTrigger.Entry pointerUp = new EventTrigger.Entry();
pointerUp.eventID = EventTriggerType.PointerUp;
pointerUp.callback.AddListener((data) => { OnPointerUp((PointerEventData)data); });
eventTrigger.triggers.Add(pointerUp);
EventTrigger.Entry pointerEnter = new EventTrigger.Entry();
pointerEnter.eventID = EventTriggerType.PointerEnter;
pointerEnter.callback.AddListener((data) => { OnPointerEnter((PointerEventData)data); });
eventTrigger.triggers.Add(pointerEnter);
}
void OnPointerDown(PointerEventData data)
{
boardController.SelectBlock(this);
}
void OnPointerUp(PointerEventData data)
{
boardController.UnSelectBlock(this);
}
void OnPointerEnter(PointerEventData data)
{
boardController.PointBlock(this);
}
#endregion
다음과 같이 EventTrigger을 만들어 사용할 수 있다.
BoardController.cs
#region Input
public void SelectBlock(BlockController block)
{
if (!canSelect)
return;
//Debug.Log(block.info.X + " , " + block.info.Y + " , "+ block.info.colorType.ToString() + block.info.blockType.ToString() + block.info.pieceType.ToString() + " Select!");
//Debug.Log(board._blocks[block.info.index].info.X + " , " + board._blocks[block.info.index].info.Y + " Select!");
canSelect = false;
selectedBlock = block;
canSwap = true;
}
public void UnSelectBlock(BlockController block)
{
if (canSelect)
return;
canSelect = true;
//Debug.Log(block.info.X + "," + block.info.Y + "UnSelect!");
}
public void PointBlock(BlockController block)
{
if (selectedBlock == null || !canSwap || canSelect || block.info.blockType == BlockType.EMPTY || block.info.blockType == BlockType.NEVER)
return;
//Debug.Log(block.info.X + "," + block.info.Y + "Point Select!");
for (int i = 0; i < 4; i++)
{
int x = selectedBlock.info.X + dx[i];
int y = selectedBlock.info.Y + dy[i];
if(block.info.X == x && block.info.Y == y)
{
canSwap = false;
canSelect = false;
targetBlock = block;
StartCoroutine(SwapBlock());
break;
}
}
}
#endregion
SelectBlock은 처음 선택한 블럭이고, PointBlock은 selectBlock이 존재할 때, 주변 4방향의 블럭으로 포인트를 갖다댈 시 발생하는 함수이다.
마우스 클릭 - selectedBlock
마우스 드래그 - targetBlock
Swap
BoardController.cs
교체할 수 있는지 없는지 검사
InitBoardMatch(BFSMode.Match) 은 너무 길기 때문에 다음 포스트에 다시 정리
-> 매치할 수 있는것이 있는지 탐색하기 위한 함수
SortBoard -> Block의 x,y값을 계산하여 자동으로 배열 내 순서를 변경
ChangeBlockValue -> 두 Block의 값을 변경하고 위치를 변경함
IEnumerator SwapBlock()
{
//Debug.Log("Swap Start");
CanMove--;
ChangeBlockValue(selectedBlock, targetBlock);
if (InitBoardMatch(BFSMode.Match))
{
while (isCoroutineAcitve)
yield return null;
targetBlock = null;
selectedBlock = null;
StartCoroutine(BlockDownAndRespawn());
}
else
{
CanMove++;
while (isCoroutineAcitve)
yield return null;
ChangeBlockValue(selectedBlock, targetBlock);
canSwap = true;
canSelect = true;
}
Managers.UI.FindPopup<UI_BoardPopup>().RefreshUI();
}
private void SortBoard()
{
Array.Sort(board._blocks, delegate(BlockController b1, BlockController b2)
{
return b1.info.index.CompareTo(b2.info.index);
});
}
void ChangeBlockValue(BlockController A, BlockController B, bool DirectMove = false, float speed = 1)
{
Vector3 APos = board._cells[A.info.X, A.info.Y].transform.position;
Vector3 BPos = board._cells[B.info.X, B.info.Y].transform.position;
Block temp = new Block(A.info);
StartCoroutine(A.MoveToTarget(BPos, B.info, speed));
if (DirectMove)
B.MoveToTargetDirect(APos, temp);
else
StartCoroutine(B.MoveToTarget(APos, temp, speed));
SortBoard();
}
BlockController.cs
public IEnumerator MoveToTarget(Vector3 Target, Block other, float speed = 2)
{
BoardController.isCoroutineAcitve = true;
info.X = other.X;
info.Y = other.Y;
while ((Target - transform.position).sqrMagnitude > 0.001f)
{
transform.position = Vector3.MoveTowards(transform.position, Target, speed * 500 * Time.deltaTime);
yield return null;
}
transform.position = Target;
BoardController.isCoroutineAcitve = false;
}