2023년 10월 4일 수요일

Line Animation

 게임을 만들다 보면 움직이는 선이 필요할 경우가 있습니다. 이런 상황처럼 말이죠.


이 동영상에도 방법이 자세하게 나와 있지만, 간단하게 다시한번 정리하겠습니다. 여기서는 SOS 신호가 전해지는 모습을 구현해보도록 하겠습니다.

가장 먼저 이 SOS라인을 만들 패턴을 만들어야겠죠. 이와 같은 SOS라인들을 만들었습니다.


이 패턴을 6개로 잘라 쓰면 되는데, 버전문제인지 Material에서는 유니티에서 스플릿한 스프라이트를 적용할 수 없더군요. 어쩔 수 없이 이렇게 일일이 잘라놓습니다1).


다음에는 line을 만들어야겠죠. Effect → Line으로 Line오브젝트를 하나 만들고 적당한 길이로 늘입니다. Line이란 것은 나중에 필요할때 시작점과 끝점을 지정해야 하므로 여기서는 아무렇게나 늘여도 됩니다.

이 line에 여러가지 속성을 넣기 위해서는 Material을 적용해야 합니다. 이미 준비된 매터리얼을 쓸 수도 있지만 우리가 필요한 매터리얼을 만들어야 합니다.
이것은 텅 빈 매터리얼이죠. 여기에 우리가 필요한 패턴을 넣도록 해 봅시다. Shared를 Standard로 한 상태에서 아까 만들었던 패턴들 중 하나를 Albedo 옆의 칸에 집어넣습니다.

다음에는 Shader를 Sprite→Default로 바꿔줍니다.

이로써 라인에 적용할 매터리얼이 완성되었습니다. 이제 이 매터리얼을 라인에 적용해야겠죠.

방금 만든 매터리얼을 라인의 Material에 끌어다 놓고 TextureMode를 Tile로 바꿉니다. 그러면 보다시피 단 하나의 패턴만 보이죠. 이것을 수정하기 위해 1)에서 만들었던 패턴의 속성을 바꿔야 합니다. 물론 6개 모두 바꿔야 하므로 이들 전체를 선택하고 WarpMode를 Repeat로 바꾸면 그림과 같이 패턴이 반복되어 나타나게 되죠.

이제 남은 것은 이 패턴을 움직이게 하는 것입니다. 이것은 스크립트에서 해야 합니다.
이 라인에 새로운 스크립트 Animate.cs를 만들어 붙입니다.

이 스크립트에서 필요한 것은, 라인을 조작할 LineRenderer와 라인을 움직이게 할 패턴입니다. 이들을 위한 변수를 만들고

라인 인스펙터에서 sosPattern에 필요한 패턴들을 끌어다 넣습니다.

다음과 같이 일정시간마다 lineRendr의 texture에 각 패턴을 차례로 집어넣으면

    // Update is called once per frame
    void Update()
    {
        if((nextFrame -= Time.deltaTime) < 0)
        {
            if(++frame >= sosPattern.Length)
                frame = 0;

            lineRendr.material.SetTexture("_MainTex", sosPattern[frame]);

            nextFrame = 0.3F;
        }
    }

이런 움직이는 라인이 완성됩니다.

이 라인을 prefab으로 만들어 필요할 때마다 instantiate로 로드해서 사용하면 끝

2023년 6월 24일 토요일

버튼 스프라이트 바꾸기

일단 버튼을 만들고 버튼의 Image -> Source Image에 스프라이트를 넣음으로써 버튼의 모습을 바꿀 수 있습니다.


그런데 상황에 따라 버튼의 모양을 실시간으로 바꿔야 할 때가 있죠.


일단 이 버튼을 조작할 수 있는 스크립트를 만듧니다.

public class CanvasFieldController : CanvasBase
{
    [SerializeField] private Sprite normalSpeed;
    [SerializeField] private Sprite doubleSpeed;
    [SerializeField] private Sprite haltSpeed;

Sprite로 선언된 변수에는, public이나 [SerializeField]가 붙어있는 경우 드래그&드롭을 통해 Inspactor에서 그림데이터를 넣을 수 있습니다.


public class CanvasFieldController : CanvasBase
{
    [SerializeField] private Sprite normalSpeed;
    [SerializeField] private Sprite doubleSpeed;
    [SerializeField] private Sprite haltSpeed;

    private Button btnGameSpeed;
    void Awake()
    {
        var gameSpeed = GameObject.Find("GameSpeed");
        btnGameSpeed = gameSpeed.GetComponent<Button>();
        btnGameSpeed.onClick.AddListener(GameSpeed);
    }
    private void GameSpeed()
    {
        Sprite spr = normalSpeed;
        switch(DT.NextScale())
        {
        case DT.TimeScale.Halt: spr = haltSpeed; break;
        case DT.TimeScale.Normal: spr = normalSpeed; break;
        case DT.TimeScale.Double: spr = doubleSpeed; break;
        default:
            false.Assert("Invalid enum");
            break;
        }
        var img = btnGameSpeed.GetComponent<Image>();
        img.AssertNotNull("Image null");
        img.sprite = spr;
    }
}

와 같이 버튼에서 Image 컴포넌트를 꺼내서 sprite변수에 넣는 식으로 버튼의 모양을 바꿀 수 있습니다.


2023년 1월 13일 금요일

슬라이더 색상 변경

 


와 같은 슬라이더가 있습니다. 이 슬라이더의 색을 바꾸는 것은 간단하죠.



여기서 화살표 부분을 선택하면 색을 바꾸는 메뉴가 나옵니다.
그런데 스크립트에서 이 작업을 하려고 하면 어떨까요?

일단은 Canvas에서 슬라이더를 찾아야 합니다.


        GameObject timeFlow = wideCanvas.transform.Find("TimeFlow").gameObject;
        Slider slider = timeFlow.GetComponent<Slider>();

위의 트리형 Hierarchy창을 보면 TimeFlow의 차일드 Fill Area, 그리고 다시 그 차일드 Fill로 구성되어 있음을 알 수 있습니다. 그러므로 fill 부분의 색을 바꾸기 위해서는,
(TimeFlow는 slider를 컴포넌트로 가지고 있는 오브젝트이므로 slider.gameObject에 해당)

        GameObject timeFlow = wideCanvas.transform.Find("TimeFlow").gameObject;
        Slider slider = timeFlow.GetComponent<Slider>();
        slider.gameObject.transform
            .Find("Fill Area")  // transform 밑의 Fill Area 찾기
                .Find("Fill")   // 또 그 아래의 Fill 찾기
                    .GetComponent<Image>()   // Image를 얻어
                        .color = Color.red;     // 색 바꾸기

마찬가지로 나머지 부분도 색을 바꿀 수 있습니다.

        GameObject timeFlow = wideCanvas.transform.Find("TimeFlow").gameObject;
        Slider slider = timeFlow.GetComponent<Slider>();
        slider.gameObject.transform
            .Find("Fill Area")  // transform 밑의 Fill Area 찾기
                .Find("Fill")   // 또 그 아래의 Fill 찾기
                    .GetComponent<Image>()   // Image를 얻어
                        .color = Color.red;     // 색 바꾸기
        slider.gameObject.transform
            .Find("Background")
                .GetComponent<Image>()
                    .color = Color.blue;
        slider.gameObject.transform.Find("Handle Slide Area")
            .Find("Handle")
                .GetComponent<Image>().color = Color.green;


2022년 10월 24일 월요일

충돌체크

 

붉은색 우주선이 우주정거장을 향해 총알을 발사했습니다. 이 총알이 타겟인 우주정거장에 닿았을 때 총알과 정거장 사이의 충돌이 일어나야 합니다.


이런 경우 콜라이드(Collider)를 통해 처리할 수 있습니다.


먼저 각 오브젝트(정거장, 총알)에 RigidBody와 Collider(2D일 경우에는 각각 RigidBody2D와 Collider2D)를 붙입니다.


그 후 충돌체크를 하기 위해서는 trigger와 스크립트를 추가해야 합니다.


이때 트리거는 맞는 물체(Target)에 설정합니다.


이렇게 되면 Target에 무언가 충돌이 일어나면 이벤트가 발생하게 되죠.


그 이벤트는 맞추는 물체(Bullet)의 스크립트로 전달됩니다. 즉 맞추는 쪽 C# Component에서 처리를 해야 합니다.




물론 Trigger를 Bullet에 걸고 스크립트를 Target에 넣어서 해도 동일합니다. 당연히 이때는 gameObject와 other가 바뀌게 되겠죠.






2021년 10월 12일 화요일