티스토리 뷰
집에서 잘 안되서 까폐로 왔다. 며칠간 Three.js를 만지다가 유니티를 만지니 유니티가 왜이리 무겁지라는 생각마져 들더라. 수시로 짠코드가 문제 없이 동작해야 다음으로 넘어가는 성향인데 그러기엔 컴파일러가 너무 열일하더라.
Three.js로 인디 게임 프로토 타입 만들기 같은거 해볼까도 생각이 든다. 어느정도 각이 잡이면 유니티로 넘어가는 식으로 말이다. 일단 Vulkan을 직접 사용하는 거는 접었다. 세팅해야 하는게 양이 많은데 그게 그렇게 재미있지가 않다.
WebGPU가 윈도우 말고 리눅스도 지원하면 이거 가지고 리눅스를 빌드에서 게임 엔진을 만들어서 사용할텐데 그렇지는 못한거 같다.
async void InputCheck()
{
if (_moveInput != 0) _socket.Emit("userInput", _moveInput);
await Task.Yield();
if (_serverOn) InputCheck();
}

잘 작동한다. 먼가 터미널이랑 같이 띠워넣고 작업하니 먼가 있어 보인다. 전에 다녔던 회사에선 대표가 마우스를 움직이지 않으면 자리에 안있는거로 간주하는 프로그램을 돌렸었는데 대부분 오토 마우스를 이용했지만 난 개발 해야 한다고 우분투를 돌렸다. 그 프로그램은 윈도우만 됬기 때문이다.
그냥 인풋 자체를 넘겨 주도록 한다. 플립은 유니티에서 처리하고 이게 Input을 트랙이라는 거가 있는데 그걸 10의 자리에서 처리하도록 한다.
살짝 지연 같은게 느껴진다. 보간을 넣어야 하는가 싶기도 하다.
인풋을 넘겨주는 방식으로는 안된다. 포지션을 넘겨줘야 할듯 싶다. 그리고 포지션과 포지션과에 오류가 나면 그건 보간을 해야 겠다.
보간을 해줘야 할만큼 딜레이는 없어 보인다. 플립되는거 정도만 만들자. 플립상태를 가져와서 100을 더하자.
async void PositionEmit()
{
_payload = thisPlayer.RendererNode.flipX ? thisPlayer.transform.position.x + 100 : thisPlayer.transform.position.x;
_socket.Emit("position", _payload);
await Task.Yield();
if (_positionOn) PositionEmit();
}
if (name == SocketManagerNode.thisID)
{
SocketManagerNode.thisPlayer = this;
Move(SocketManagerNode.moveInput);
}
else
{
_positionX = SocketManagerNode.ClientList[name];
_position.x = _positionX >= 100 ? _positionX - 100 : _positionX;
transform.position = _position;
RendererNode.flipX = SocketManagerNode.ClientList[name] >= 100;
}
계속 보고 있으면 아주 가끕씩 살짝 튀긴 하는데 크겐 문제가 안될듯 싶다.
완성이다. 이걸 강의로 만들지 말지는 조금 고민을 해봐야 할꺼 같다. 내용 자체가 쉽지는 않으니 말이다.
플레이어 무브
using UnityEngine;
namespace Main
{
public class PlayerMove : MonoBehaviour
{
float MoveSpeed => 5f;
SocketManager SocketManagerNode => FindObjectOfType<SocketManager>();
Animator AnimatorNode => GetComponent<Animator>();
public SpriteRenderer RendererNode => GetComponent<SpriteRenderer>();
int Walk => Animator.StringToHash("Walk");
Vector3 _position = new(0, -1.25f, -1f);
Vector3 _move = new();
float _positionX = 0;
void Update()
{
if (name == SocketManagerNode.thisID)
{
SocketManagerNode.thisPlayer = this;
Move(SocketManagerNode.moveInput);
}
else
{
_positionX = SocketManagerNode.ClientList[name];
_position.x = _positionX >= 100 ? _positionX - 100 : _positionX;
transform.position = _position;
RendererNode.flipX = SocketManagerNode.ClientList[name] >= 100;
}
}
void Move(float input)
{
AnimatorNode.SetBool(Walk, input != 0);
RendererNode.flipX = input < 0 ? true : input > 0 ? false : RendererNode.flipX;
_move.x = input * MoveSpeed * Time.deltaTime;
transform.position += _move;
}
}
}
소캣메니져
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
namespace Main
{
public class SocketManager : MonoBehaviour
{
SocketIOUnity _socket;
int Port => 3000;
public string thisID;
public List<PlayerMove> playerMoveList;
public PlayerMove thisPlayer;
public Dictionary<string, float> ClientList;
bool _playerSet;
bool _positionOn;
public float moveInput = 0;
float _payload = 0;
Transform _playerManager;
Button _disconnectButton;
Button _connectButton;
void Awake()
{
_disconnectButton = GameObject.Find("Disconnect").GetComponent<Button>();
_disconnectButton.onClick.AddListener(Disconnect);
_connectButton = GameObject.Find("Connect").GetComponent<Button>();
_connectButton.onClick.AddListener(Connect);
_playerManager = GameObject.Find("PlayerManager").transform;
playerMoveList = _playerManager.GetComponentsInChildren<PlayerMove>().ToList();
foreach (var player in playerMoveList)
{
player.gameObject.SetActive(false);
}
}
void Start()
{
MainThreadRun();
SocketThreadRun();
}
void Update()
{
moveInput = Input.GetAxis("Horizontal");
}
void MainThreadRun()
{
PlayerSet();
}
async void PlayerSet()
{
while (!_playerSet) await Task.Yield();
_positionOn = false;
if (ClientList != null)
{
PlayerInit();
int index = 0;
foreach (var client in ClientList)
{
if (index >= playerMoveList.Count)
{
print("We need more players!");
index += 1;
continue;
}
print($"{client.Key} is positionX {client.Value}");
playerMoveList[index].gameObject.SetActive(true);
playerMoveList[index].name = client.Key;
playerMoveList[index].transform.position = new Vector3(client.Value, -1.25f, -1f);
index += 1;
}
thisPlayer = playerMoveList.Find(i => i.name == thisID);
print($"{thisPlayer.name} is ready!");
}
else
{
_playerSet = false;
PlayerSet();
}
_positionOn = true;
PositionEmit();
_playerSet = false;
if (!_playerSet) PlayerSet();
}
void PlayerInit()
{
foreach (var player in playerMoveList)
{
player.gameObject.SetActive(false);
player.name = "Player";
player.transform.position = new Vector3(0f, 0f, 0f);
}
}
void SocketThreadRun()
{
_socket = new SocketIOUnity($"http://localhost:{Port}");
_socket.Connect();
_socket.OnConnected += async (sender, eventArgs) =>
{
thisID = _socket.Id;
print($"{thisID} is connected!");
};
_socket.On("playerSet", clientList =>
{
try
{
_playerSet = true;
ClientList = clientList.GetValue<Dictionary<string, float>>();
}
catch (Exception exception)
{
Debug.LogError(exception.Message);
throw;
}
});
_socket.On("updatePlayer", clientList =>
{
try
{
ClientList = clientList.GetValue<Dictionary<string, float>>();
}
catch (Exception exception)
{
Debug.LogError(exception);
throw;
}
});
_socket.OnDisconnected += async (sender, eventArgs) =>
{
print($"{thisID} is disconnected!");
_playerSet = false;
PlayerInit();
};
}
async void PositionEmit()
{
_payload = thisPlayer.RendererNode.flipX ? thisPlayer.transform.position.x + 100 : thisPlayer.transform.position.x;
_socket.Emit("position", _payload);
await Task.Yield();
if (_positionOn) PositionEmit();
}
void OnApplicationQuit()
{
PlayerInit();
_socket.Disconnect();
}
void Disconnect()
{
_socket?.Disconnect();
}
void Connect()
{
_socket?.Connect();
}
}
}
서버
'학습 > AWS' 카테고리의 다른 글
영상으로 만들어야지 (0) | 2024.08.28 |
---|---|
그냥 서버도 내가 맡겠다고 (1) | 2024.08.28 |
전회사가 잘되는 꿈을 꾸다니 (0) | 2024.08.27 |
꼼수일수도 있는데 (0) | 2024.08.27 |
쓰래드 문제 (0) | 2024.08.26 |