적 근접전투

턴제제작 2019. 4. 11. 04:50

 

 아마 슬럼프의 원인이 복잡한 기능을 만들려다 보니 번아웃이 되었나 보다. 코드를 가져와서 쓰는 것보다 새로 코드를 만들어 내는 게 좀 더 힘이 드는 거 같다. 일단 근접 전투까지 만들고 잠시 프로젝트는 쉬면서 당분간은 학습의 시간을 가져야겠다. 

  일단 적 캐릭터에게 무기를 쥐어 주는 것부터 작업을 해야 겠다. 

 이제 무기가 없어서 도망다니던건 필요 없어진 듯싶다. 

 근데 이 오류는 왜 뜨는지 모르겠네... 아 플레이어로 되어 있어서 그리고나... 에너미에도 호환되게 바꿀 필요가 있는 듯싶다. 

    void Start()

    {

        RaycastHit[] hit;

        hit = Physics.BoxCastAll (this.transform.position + pos, Vector3.one, Vector3.forward, Quaternion.identity, LayerMask.GetMask (layerName));     

 

        foreach (var Owner in hit)

        {           

            if (Owner.transform.tag == "Player")

            {

                player = Owner.transform.GetComponent <Player>();

                player.baseWeapon = this;

                return;

            }

            else if (Owner.transform.tag == "Enemy")

            {

                enemy = Owner.transform.GetComponent <Enemy>();

                enemy.baseWeapon = this;

                return;

            }

        }

        

        EquipSword();

    }

 굳이 번거로운 이런 시스템을 만든 이유는 매번 캐릭터마다 무기를 드래그 앤 드롭해서 등록시키기 귀찮기 때문이다. 

 기본적인 전투 준비는 끝이 났다. 무기와 머리색은 깔맞춤을 했다. 

    void Awake()

    {

        boxCollider = this.transform.GetChild (0). GetComponent <BoxCollider>();

        EquipSword();

    }

 끝난 줄 알았는데 버그가 있었다.

 죽을 때 검을 놓치는 모션을 넣어야 할 듯싶다. 일단은 그건 뒤로 미루고 전투 시스템부터 구현하도록 하자. 

 문득 드는 생각이 이번까지만 코딩을 하고 그다음부터는 리틀 데빌 인사이트 같은 근사한 트레일러 애니메이션을 만드는데 주력해야 할 듯싶다. 그렇게 해서 애니메이션 실력을 늘리고 말이다. 틈날 때마다 애니메이션 강의 영상을 보고 있다. 

 이번 프로젝트가 끝나면 그다음에는 내 전공인 사회 과학을 살려서 문명 같은 시뮬레이션을 만들어 보고 싶은 생각이 있다. 

 랜덤 워크로 되어 있는 부분을 타격 범위에 있을 때는 가서 때리고 그렇지 않은 경우에는 랜덤워크를 하도록 바꿔야 할 듯싶다. 거기까지만 하고 애니메이션을 연습하러 가야겠다. 일단 기본기를 익힌 후에 기존에 있는 애니메이션을 모방해서 따라 만드는 것부터 하고 그다음에 본격적으로 창작의 영역으로 넘어가야겠다. 한 세 달 정도 쓰면 되려나 쉽기도 하다. 

IEnumerator DoEnemies (string order)

{

foreach (var enemy in gameManager.activeEnemyList)

{

currentEnemy = enemy;

 

var doSomethig = currentEnemy.baseVigor;

var condition = new WaitUntil (() => currentEnemy.currentVigor <= 0);

var oneMore = new WaitUntil (() => currentEnemy.currentVigor < doSomethig);

 

while (currentEnemy.currentVigor > 0)

{

if (order == "Base")

{

currentEnemy.RandomWalk (order);

yield return oneMore;

doSomethig -= 1;

}

if (order == "Double")

{

currentEnemy.RandomWalk (order);

yield return oneMore;

doSomethig -= 2;

}

}

yield return condition;

currentEnemy.turnState = TurnState.Ending;

}

gameManager.CheckEnemyTurn();

}

 지금 여기에 무조건 랜덤 워크를 하도록 되어 있다. 

    public void Attack ()

    {

        

    }

 일단은 근처에 플레이어 유닛들이 있는지 없는지부터 감지를 해야 될 듯싶다. 있으면 공격을 하러 가고 없으면 그냥 랜덤 워크를 하면 될듯 싶다. 그리고 감지가 되면 근접해서 이동을 하도록 하면 될듯 싶다. 그다음에 공격 모션을 넣어주면 될듯 싶다. 아 그리고 일단은 감지된 것 중에 근접해서 가서 때리는 최대 8자리 중에서 랜덤으로 가서 때리도록 해야 할 듯싶다.

 감지를 어떻게 하나 플레이어 쪽 스크립트를 봤다. 에너미 쪽에서 찾아가는 게 아니라 거꾸로 플레이어에서 내 주변에 에너미 이동 가능 에어리어가 있으면 알려주는 걸로 해야 될 듯싶다. 

 일단 현재 액티브 되어 있는 플레이어 리스트를 불러와야 될 듯싶다. 

    public void Attack()

    {

        foreach (var player in gameManager.activePlayerList)

        {

            foreach (var direction in GameUtility.eightDirections)

            {

                RaycastHit hit;

                if (Physics.Raycast (player.transform.position, direction, out hit, GameUtility.interval *alpha, LayerMask.GetMask ("")))

                {

                    

                }

            }

 

        }

    }

 현재 탐색을 하고 있는 에너미의 사정거리에 드는지를 확인해야 될 듯싶다. 일단 너무 밤이 되면 식사할곳이 마땅치 않으니 밥부터 먹고 와야 될듯 싶다. 사정거리에 들면 사정거리에 드는 플레이어의 리스트를 만들고 거기서 누구를 선택할지 결정해야 할 듯싶다. 나중에는 효용이 가장 높은 걸 선택하겠지만 일단은 랜덤 하게 선택을 하도록 하자. 

    public void BaseCloseAttack()

    {

        var closeCombatList = new List <TileNode>();

 

        foreach (var player in gameManager.activePlayerList)

        {

            foreach (var direction in GameUtility.eightDirections)

            {

                RaycastHit hit = new RaycastHit();

                Physics.Raycast (player.transform.position, direction, out hit, GameUtility.interval);

 

                if (hit.transform == null) continue;

                

                if (hit.transform.GetComponent <TileNode>(). tileStyle == TileStyle.OneArea ||

                hit.transform.GetComponent <TileNode>(). tileStyle == TileStyle.TwoArea)

                {

                    closeCombatList.Add (hit.transform.GetComponent <TileNode>());

                }

            }

 

        }

    }

 플레이어의 경우를 참고해서 이런 식으로 만들어 봤는데 이경우 선행되어야 할 것이 타일을 바꾸어 주는 일이다. 

 두통의 원인이 주간에 활동을 해서 그런 듯싶다. 저녁 6시쯤 일어나서 다음날 아침까지 작업하고 잠에 들면 해당 문제가 발생하지 않는다. 내가 야행성 인간인데 낮에 활동하게 되니까 두통이 발생하게 된 거였다. 그리고 세상에 정적이 감돌아야 작업이 더 잘되는 듯싶다. 이게 타일 시스템으로 만드니까 코딩이 번거로워지니 차기작에는 그리드 기반이 아니라 그냥 디비니티 오리지널 씬과 같은 자유로운 방식으로 만들러야 할 듯싶다. 

 생각보다 다른 점이 있어서 리셋 보드와는 별개의 함수를 만들어야 할 듯싶다. 가령 바운더리 같은 건 만들 필요가 없기 때문이다. 작업의 경우에는 앞에 만들어놯던 코드를 참조하면 되는 걸 보니 가장 어려운 부분이 이 이전 단계였나 보다. 

void MoveAreaOnEnemy (Enemy enemy)

{

if (enemy == null) return;

 

if (enemy.currentVigor == 2)

{

enemy.moveDoubleArea.SetActive (true);

enemy.moveBaseArea.SetActive (true);

}

else if (gameManager.currentPlayer.currentVigor == 1)

{

enemy.moveDoubleArea.SetActive (false);

enemy.moveBaseArea.SetActive (true);

}

else if (gameManager.currentPlayer.currentVigor <= 0)

{

enemy.moveDoubleArea.SetActive (false);

enemy.moveBaseArea.SetActive (false);

}

}

 

void MoveAreaOffEnemy (Enemy enemy)

{

if (gameManager.currentPlayer == null) return;

 

enemy.moveDoubleArea.SetActive (false);

enemy.moveBaseArea.SetActive (false);

}

  왠지 슬슬 다시 코딩이 재미있어지기 시작하는 듯싶다. 

public void ResetEnemyBoard()

{

FindEnemyNode (enemyAI.currentEnemy);

MoveAreaOnEnemy (enemyAI.currentEnemy);

 

foreach (var node in NodeList)

{

node.gameObject.layer = LayerMask.NameToLayer ("Node");

node.tileStyle = TileStyle.Normal;

node.shieldStyle = ShieldStyle.Default;

SetTileStyle (node);

}

 

MoveAreaOnEnemy (enemyAI.currentEnemy);

}

 이렇게 만들어 놓으면 되려나 싶다. 

    public void CloseAttack()

    {

        board.ResetEnemyBoard();

 

        var closeCombatList = new List <TileNode>();

 

        foreach (var player in gameManager.activePlayerList)

        {

            foreach (var direction in GameUtility.eightDirections)

            {

                RaycastHit hit = new RaycastHit();

                Physics.Raycast (player.transform.position, direction, out hit, GameUtility.interval);

 

                if (hit.transform == null || hit.transform.GetComponent <TileNode>() == null) continue;

                

                if (hit.transform.GetComponent <TileNode>(). tileStyle == TileStyle.OneArea ||

                hit.transform.GetComponent <TileNode>(). tileStyle == TileStyle.TwoArea)

                {

                    print (this.name + "is enable to close cambat");

                    closeCombatList.Add (hit.transform.GetComponent <TileNode>());

                }

            }

 

        }

    }

 이 부분을 수정했더니 인지가 되는 듯하다. 이제 클로우즈 컴뱃이 가능한 경우에는 랜덤 워크를 하는 게 아니라 플레이어 가까이로 이동하도록 해야겠다. 

IEnumerator DoEnemies (string order)

{

foreach (var enemy in gameManager.activeEnemyList)

{

currentEnemy = enemy;

 

var doSomethig = currentEnemy.baseVigor;

var condition = new WaitUntil (() => currentEnemy.currentVigor <= 0);

var oneMore = new WaitUntil (() => currentEnemy.currentVigor < doSomethig);

 

var closeAttackPosition = currentEnemy.CloseAttack();

 

if (closeAttackPosition.Count == 0)

{

while (currentEnemy.currentVigor > 0)

{

if (order == "Base")

{

currentEnemy.RandomWalk (order);

yield return oneMore;

doSomethig -= 1;

}

 

if (order == "Double")

{

currentEnemy.RandomWalk (order);

yield return oneMore;

doSomethig -= 2;

}

}

}

 

yield return condition;

currentEnemy.turnState = TurnState.Ending;

}

gameManager.CheckEnemyTurn();

}

 이제 랜덤 한 자리로 이동하게 하면 될 듯싶다.

 문득 애니메이션의 경우에는 모션 캡처로 초벌을 만들고 블렌더로 수정을 하면 되지 않을까 생각 중이다. 키넥트를 사서 캡처하면 되려나 싶다. 

 키넥트가 단종됐네. 머 생각처럼 풀리지 않는 듯싶다. 일단 애니메이션과 모델링에 모든 역량을 쏟아부어야겠다. 프로그래밍은 이만하면 된 듯싶다. 

    public void UnitWalk (string order, TileNode endNode = null, string walkOrder = "Random")

    {

        TileNode newNode = endNode;

 

        if (walkOrder == "Random")

        {

            var areaList = new List <TileNode>();

            if (order == "Base")

            {

                moveBaseArea.SetActive (true);

            }

            else if (order == "Double")

            {

                moveDoubleArea.SetActive (true);

            }

            else

            {

                print ("Wrong order for RandomWalk");

            }

 

            foreach (var node in board.NodeList)

            {

                if (Physics.CheckBox (node.transform.position, box, Quaternion.identity, LayerMask.GetMask ("Obstacle", "Player", "Enemy")))

                {

                    continue;

                }

                if (order == "Base")

                {

                    if (Physics.CheckBox (node.transform.position, box, Quaternion.identity, LayerMask.GetMask ("MoveBaseArea")))

                    {

                        areaList.Add (node);

                        node.tileStyle = TileStyle.OneArea;

                    }

                    

                }

                else if (order == "Double")

                {

                    if (Physics.CheckBox (node.transform.position, box, Quaternion.identity, LayerMask.GetMask ("MoveDoubleArea")))

                    {

                        areaList.Add (node);

                        node.tileStyle = TileStyle.TwoArea;

                    }

                }

            }

 

            // print ("Node count : " + areaList.Count);

            int randomNumber = Random.Range (0, areaList.Count -1);

            newNode = areaList [randomNumber];

            // print ("End node : " + endNode);

            if (order == "Base")

            {

                moveBaseArea.SetActive (false);

            }

            else if (order == "Double")

            {

                moveDoubleArea.SetActive (false);

            }       

        // GameObject.Instantiate (flag, endNode.transform.position, Quaternion.identity);

        }

 

        else if (walkOrder == "BaseClose")

        {

            newNode = endNode;

        }

 

        Moving (newNode, board.NodeList, order);

    }

IEnumerator DoEnemies (string order)

{

foreach (var enemy in gameManager.activeEnemyList)

{

currentEnemy = enemy;

 

 

var doSomethig = currentEnemy.baseVigor;

var condition = new WaitUntil (() => currentEnemy.currentVigor <= 0);

var oneMore = new WaitUntil (() => currentEnemy.currentVigor < doSomethig);

 

var closeAttackPositionList = currentEnemy.CloseAttack();

 

if (closeAttackPositionList.Count == 0)

{

while (currentEnemy.currentVigor > 0)

{

if (order == "Base")

{

currentEnemy.UnitWalk (order);

yield return oneMore;

doSomethig -= 1;

}

 

if (order == "Double")

{

currentEnemy.UnitWalk (order);

yield return oneMore;

doSomethig -= 2;

}

}

}

 

else if (closeAttackPositionList.Count!= 0)

{

int randomInt = UnityEngine.Random.Range (0, closeAttackPositionList.Count -1);

var closeAttackPositionRandom = closeAttackPositionList [randomInt];

print (closeAttackPositionRandom);

 

while (currentEnemy.currentVigor > 0)

{

if (order == "Base")

{

currentEnemy.UnitWalk (order, closeAttackPositionRandom, "BaseClose");

yield return oneMore;

doSomethig -= 1;

}

 

if (order == "Double")

{

currentEnemy.UnitWalk (order, closeAttackPositionRandom, "BaseClose");

yield return oneMore;

doSomethig -= 2;

}

}

}

 

yield return condition;

currentEnemy.turnState = TurnState.Ending;

}

 

gameManager.CheckEnemyTurn();

}

 살짝 이해할 수가 없는 오류가 있어서 통합했다. 아 그리고 이전 캐릭터 타일 노드가 초기화되지 않는 버그가 있어서 그것도 수정해야 할 듯싶다. 

public void ResetEnemyBoard (Enemy enemy)

{

if (enemy == null) return;

 

foreach (var node in nodeList)

{

node.tileStyle = TileStyle.Normal;

}

 

FindEnemyNode (enemy);

MoveAreaOnEnemy (enemy);

 

 

foreach (var node in NodeList)

{

node.gameObject.layer = LayerMask.NameToLayer ("Node");

node.tileStyle = TileStyle.Normal;

node.shieldStyle = ShieldStyle.Default;

SetTileStyle (node);

}

 

MoveAreaOffEnemy (enemy);

}

 이 부분은 off를 안 해줬더라. 

void MoveAreaOffEnemy (Enemy enemy)

{

if (enemy == null) return;

 

enemy.moveDoubleArea.SetActive (false);

enemy.moveBaseArea.SetActive (false);

}

 이제 제대로 작동한다. 이제 공격하는 것만 만들면 될 듯싶다. 그런데 랜덤으로 하니까 굳이 뺑 돌아가는 일이 생겨서 돌아가지 말고 여러 노드 중에서 최단거리 노드를 찾아가는 게 더 현명할 듯싶다. 각 노드와 유닛 간에 거리를 구하고 최소 값인 노드를 찾아가도록 해야겠다. 

    public void BaseCloseAttack()

    {

        print (gameManager.currentPlayer.activeState);

 

        currentEnemyList = null;

        currentEnemyList = new List <Enemy>();

 

        foreach (var direction in GameUtility.eightDirections)

        {

            RaycastHit hit;

            if (Physics.Raycast (transform.position + Vector3.up, direction, out hit, GameUtility.interval *alpha, LayerMask.GetMask ("Enemy")))

            {

                if (hit.transform == null) continue;

                if (hit.transform.GetComponent <Enemy>(). activeState == ActiveState.Dead) continue;

 

                hit.transform.LookAt (this.transform);

                

                var enemy = hit.transform.GetComponent <Enemy>();

                enemy.direction = direction;

                currentEnemyList.Add (enemy);

            }

        }

 

        if (currentEnemyList == null) return;

        StartCoroutine (AllEnemy (2f));

    }

 중간에 버그를 발견해서 죽은 적은 무시하도록 했다. 

public TileNode ShortNode (Vector2 startPos , List <TileNode> nodeList)

{

var newNode = new TileNode();

 

foreach (var node in nodeList)

{

node.distance = 0f;

node.distance = Vector2.Distance (startPos, node.Coordinate);

}

 

var minDistance = nodeList.Min (n => n.distance);

newNode = nodeList.Find (n => n.distance == minDistance);

 

return newNode;

}

 일단 최솟값을 찾는 걸 만든다. 이게 함수형 C#을 쓰는 게 익숙하지 않아서 좀 했갈렸다. C#이 트렌드가 함수형 프로그래밍을 적극적으로 사용하도록 넘어가서 이 부분을 추가적으로 공부를 해야 할 듯싶다. 애니메이션 공부를 하기 전에 이부분을 확실히 잡고 넘어가야 할듯 싶다. 

 돌아서 가지 않고 최단 거리 노드로 간다. 물론 지금은 플레이어 유닛들을 구분하지 않고 최단거리로 가는 경향이 있다. 따라서 후방에 있는 약한 적을 대상으로 파고들기를 하지 않는 문제가 있다. 이건 차후에 인공지능을 정교하게 만들 때 고려하도록 해야겠다. 이제 전투 시스템을 만들면 될 듯싶다. 아마 이건 저번에 플레이어 공격 시스템 만들었던 거랑 같은 방식으로 만들면 된다. 아 그리고 이동할 필요가 없으면 그냥 움직이지 않고 때리는 것도 만들어야 한다. 일단 핵심 기능부터 만들고 그건 천천히 만들도록 하자. 

 여기서 공격하는 걸 만드는 건 생각보다 어려울 수가 있다. 저번에 이걸 만드느라 진이 빠진 듯싶다. 

 일단 만들려고 시도를 했는데 좌표뿐만 아니라 타격하는 적이 누 군인 지도 매개변수로 누구인지 알려줄 필요가 있는 듯싶다. 나중에 효용 중심으로 선택하게 하려면 플레이어를 상위로 놓고 하위로 타일 노드들을 선택하게 해야겠다. 일단은 플레이어를 랜덤으로 선택하게 하고 그 플레이어에 속한 노드 중에서 가까운 타일 노드로 가서 선택하게 하는 시스템을 만들어야 할 듯싶다. 

    public List <Player> CloseAttackList()

    {

        board.ResetEnemyBoard (enemyAI.currentEnemy);

        var closeCombatList = new List <Player>();



        foreach (var player in gameManager.activePlayerList)

        {

            foreach (var direction in GameUtility.eightDirections)

            {

                RaycastHit hit = new RaycastHit();

                Physics.Raycast (player.transform.position, direction, out hit, GameUtility.interval);

 

                if (hit.transform == null || hit.transform.GetComponent <TileNode>() == null) continue;

                

                if (hit.transform.GetComponent <TileNode>(). tileStyle == TileStyle.OneArea ||

                hit.transform.GetComponent <TileNode>(). tileStyle == TileStyle.TwoArea)

                {

                    if (closeCombatList.Find (i => i == player))

                    {

                        player.closeList.Add (hit.transform.GetComponent <TileNode>());

                    }

                    else

                    {

                        closeCombatList.Add (player);

                        player.closeList.Add (hit.transform.GetComponent <TileNode>());

                    }

                }

                else

                {

                    // print (this.name + " can not enable to close cambat");

                }

            }

        }

        

        // print (closeCombatList.Count);

        return closeCombatList;

    }

 꽤 많이 수정했다. 

else if (closeAttackList.Count!= 0)

{

int randomInt = UnityEngine.Random.Range (0, closeAttackList.Count -1);

var newPlayer = closeAttackList [randomInt];

 

var newNode = ShortNode (GameUtility.Coordinate (enemy.transform.position), newPlayer.closeList);

 

while (currentEnemy.currentVigor > 0)

{

if (order == "Base")

{

currentEnemy.UnitWalk (order, newNode, "BaseClose");

yield return oneMore;

doSomethig -= 1;

}

 

if (order == "Double")

{

currentEnemy.UnitWalk (order, newNode, "BaseClose");

yield return oneMore;

doSomethig -= 2;

}

}

 

// enemy.CloseAttack (player);

}

 이경우 이미 이동한 자리에 또 가서 자리 잡는 경향이 있다 그걸 좀 수정해 주어야겠다. 

    public List <Player> CloseAttackList()

    {

        board.ResetEnemyBoard (enemyAI.currentEnemy);

        var closeCombatList = new List <Player>();



        foreach (var player in gameManager.activePlayerList)

        {

            player.closeList = new List <TileNode>();

            

            foreach (var direction in GameUtility.eightDirections)

            {

                RaycastHit hit = new RaycastHit();

                Physics.Raycast (player.transform.position, direction, out hit, GameUtility.interval);

 

                if (hit.transform == null || hit.transform.GetComponent <TileNode>() == null) continue;

                var newTile = hit.transform.GetComponent <TileNode>();

                

                if (newTile.tileStyle == TileStyle.OneArea ||

                newTile.tileStyle == TileStyle.TwoArea)

                {

                    if (closeCombatList.Find (i => i == player))

                    {

                        player.closeList.Add (newTile);

                    }

                    else

                    {

                        closeCombatList.Add (player);

                        player.closeList.Add (newTile);

                    }

                }

                else

                {

                    // print (this.name + " can not enable to close cambat");

                }

            }

        }

        

        // print (closeCombatList.Count);

        return closeCombatList;

    }

 리스트를 초기화를 안 해줘서 그런 거였다. 이제 모션을 추가해 보도록 하자. 

 작동하는데 이미 죽은 경우에는 굳이 가서 공격하지 않도록 바꿔줘야겠다. 

 플레이어가 한 명 죽었을 때 턴이 돌아오면 버그가 생긴다. 이문제를 좀 해결해 주어야겠다.   

    public void CloseAttack (Player player, float farFrom = 1)

    {   

        ending = false;

        animator.SetTrigger ("BaseAttack");

        this.transform.LookAt (player.transform);

        player.transform.LookAt (this.transform);

 

        StartCoroutine (WaitSkillUsed (player, farFrom));

        

    }

 

    IEnumerator WaitSkillUsed (Player player, float farFrom)

    {

        model.position = this.transform.position;

 

        if (player.direction == Vector3.forward ||

            player.direction == Vector3.back ||

            player.direction == Vector3.left ||

            player.direction == Vector3.right)

        {

            model.position = this.transform.position - player.direction / farFrom;

        }

        else

        {

            model.position = this.transform.position + player.direction / (farFrom + farFrom);

        }

        

 

while (! animator.GetCurrentAnimatorStateInfo(0). IsTag ("Action"))

{

yield return null;

}

 

        gameManager.somthingOn = true;

        ending = false;



while (animator.GetCurrentAnimatorStateInfo(0). normalizedTime < gameManager.swordHit)

{

            yield return null;

}

 

        // effects

        Instantiate (gameManager.hitLine, player.transform.position + gameManager.paticlePos, baseWeapon.transform.rotation);

        Instantiate (gameManager.hitPaticles, this.transform.position + gameManager.paticlePos, Quaternion.Euler (0, 0, gameManager.particleRotation));

        Instantiate (gameManager.hitBlood, player.transform.position + gameManager.paticlePos, player.transform.localRotation, player.transform);

 

        var damage = (int) Random.Range (baseWeapon.damageMin, baseWeapon.damageMax +1);

player.CurrentHP = player.CurrentHP - damage;

player.hpController.fill();

 

if (player.CurrentHP <= 0)

{

player.animator.SetTrigger ("Die");

            player.activeState = ActiveState.Dead;

            gameManager.activePlayerList.Remove (player);

}

else

{

player.animator.SetTrigger ("Withstand");

}

 

while (! player.animator.GetCurrentAnimatorStateInfo(0). IsTag ("Hit"))

{

yield return null;

}

        

        while (player.animator.GetCurrentAnimatorStateInfo(0). normalizedTime < gameManager.swordEndTime)

        {

            yield return null;

        }

 

        ending = true;

        model.position = this.transform.position;

        gameManager.somthingOn = false;

    }

 중간에 내가 알 수 없는 버그가 발생하면 맛이 갈 수도 있다는 생각이 든다. 여하튼 그럭저럭 완성한 거 같으니 영상을 찍고 당분간 학습을 하려 가자. 

 

'턴제제작' 카테고리의 다른 글

AI 공격 [영상]  (0) 2019.04.22
리펙토링  (0) 2019.04.20
대화 시스템  (2) 2019.04.05
다음에 할일  (7) 2019.03.16
근접 전투 [영상]  (0) 2019.03.16

WRITTEN BY
아이고이아

,