게임 개발 과정 (1) - 오토체스류(제목미정)

zebius·2025년 1월 24일
0

UnityPractice

목록 보기
2/4

1월 21일

유니티를 이용하여 오토체스류 게임을 만들기 시작했다.

게임의 스토리는 차치하고 코드개발 과정만을 기록할까 한다.

Unity에서 Data oriented design 방식인 Entity Component System(이하 ECS)이 있다는걸 배우고서 일부 데이터 처리를 ECS방식으로 만들고 싶다는 생각을 했다.

데이터 처리시 일괄 처리(batching)하여 데이터 접근에 효율을 높여주는 방식을 한번 써보고 싶었기때문이다.(아무래도 객체 지향 방식은 데이터가 각 객체 단위로 저장되어 대규모 처리시 효율이 떨어진다(cache miss)) - 필자는 초보개발자인 관계로 이정도만 이해하고 있다.

21일엔 기획과 기반이될 시스템 코드를 일부 틀을 잡았다.

//게임 시스템
public interface IGameSystem {
    void SetState(IGameState state);
}
public class GameSystem : Singleton<GameSystem>,IGameSystem{
    private IGameState CurrentState;
    private IInputHandler handler;
    private void Awake () {
        IGameOperating gameOperating=new GameOperating();
        gameOperating.Initialize();
        handler=new InputHandler();
    }
    private void Update() {
        CurrentState?.OnUpdate(this);
        if(CurrentState is InGameState inGame) {
            //여기서 카메라 이동 방향 설정,카메라 움직임은 게임 내의 중요한 이벤트는 아니라서 이벤트 발행은 굳이 필요하지 않을듯?
            var dir=handler.ReadDirection();
        }
    }
    public void SetState(IGameState state) {
        if(state==null||CurrentState==state)
            return;
        CurrentState?.OnExit(this);
        CurrentState=state;
        CurrentState?.OnEnter(this);
    }
}
/// <summary>
/// Interface Game State
/// </summary>
public interface IGameState {
    /// <summary>
    /// 상태에 진입할때 해당 상태에 맞는 UI를 구현해야함.
    /// 필요 리소스 캐싱 작업을 해야되니까 캐싱작업중 화면 멈춤등이 발생하게
    /// 하지 않으려면 비동기로 처리를 하고 메인 스레드에서는 로딩 화면을 렌더링하게 해줘야한다.
    /// </summary>
    /// <param name="system"></param>
    void OnEnter(IGameSystem system);
    /// <summary>
    /// 해당 상태에서는 업데이트 해줘야할 사항 처리.
    /// </summary>
    /// <param name="system"></param>
    void OnUpdate(IGameSystem system);
    /// <summary>
    /// 
    /// </summary>
    /// <param name="system"></param>
    void OnExit(IGameSystem system);
}

게임 상태는 Finite-State Machine 패턴을 사용하여 interface로 틀만 잡아놨다.
게임 시스템도 하나만 존재해야 하므로 Singleton 패턴을 사용하여 작성하였다.

 public class Singleton<T> : MonoBehaviour where T : MonoBehaviour{
 	private static T Instance=null;
    private static bool IsShuttdown=false;
    private static object _lock = new object();
    public static T instance{
    	get{
        	if(IsShuttdown)return null;
            //다중 스레드 접근시 안정성 보장
            lock(_lock){
            	if(Instance==null){
            		Instance=FindObjectTypeof<T>();
                	if(Instance==null){
                		GameObject go = new GameObject();
                        Instance=go.AddComponent<T>();
                        go.name=typeof(T).name+"[singleton];
                        DontDestroyOnLoad(go);                        
                	}
            	}
                return instance;
			}    
        }
        ...생략
 }

원래 위의 방식으로 사용하였으나 Lazy 초기화 지연 방식을 사용하면 Lazy 내부적으로 스레드 안전을 보장해주는 코딩이 되어있어서 아래의 방식으로 전환하였다.

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour {
	private static Lazy<T>Instance=new Lazy<T>(()=>{
    	var ret = FindObjectTypeOf<T>();
        if(ret==null){
        	GameObject go=new GameObject();
            ret=go.AddComponent<T>();
            go.name=typeof(T).name+"[Singleton]";
            DontDestroyOnLoad(go);
        }
        return ret;
    });
    public static T instance{
    	get=>Instance.Value();
    }
    ...생략
}

그리고 실행시 비디오나 소리 옵션을 초기화 해주는 GameOperating 코드 틀을 잡아놓았다.

public class GameOperating :IGameOperating{
    //json 파일로 이전에 저장되었던 어플리케이션 환경을 불러옴
    static readonly string Path="Environment.json";
    public void Initialize () {
        string path = System.IO.Path.Combine(Application.persistentDataPath,Path);
        ApplicationEnvironment environment;
        if (!File.Exists(path)) {
            Debug.Log("Environment not exist. initialize on default Setting");
            environment=new ApplicationEnvironment { resolution=UserEnvironments.Resolution.R1920x1080, isFull=true };
        }
        string str = File.ReadAllText(path);
        environment=JsonConvert.DeserializeObject<ApplicationEnvironment>(str);
        UserEnvironments.Pair<int, int> res = UserEnvironments.ResolutionMapping[environment.resolution];
        Screen.SetResolution(res.first, res.second, environment.isFull);
    }
}

newtonsoft 에서 만든 json api를 이용하여 게임 옵션값들을 빠르게 Json으로 변경하여 입출력하게 만들었다. 추후 소리등의 설정은 추가할 예정이다.

profile
스타터입니다.

0개의 댓글

관련 채용 정보