버벅이는 현상이 보여서 스크립트를 찾아봤다.

Sprite를 코루틴으로 교체하던 부분이었고 큰 문제는 없어보였다.

현상이 확인되는 시점이 데이터가 확 들어오는 타이밍과 동시라 일이 생겼던 걸까.

비동기로 처리하면 되지 않을까 싶어서 비동기 처리 방식을 찾아봤다.

 

그런데, async를 이용하니 Sprite가 변경이 안 되는 것이었다.

async를 쓰면서 while문은 처리할 수 없는건가? 싶었는데 그건 아니었다.

 

로그를 찍어보니 sprite를 바꿔주는 부분에서 걸렸다.

 

while(true)

{

num++

mainImage.sprite = sprites[num]

}

 

여러곳을 찾아본 결과.. 멀티 스레드에서 메인 스레드의 기능을 쓸 때 유니티 자체에서 전부 쓸 수 없도록 제한을 해놨던 것이었다.

 

즉, 멀티스레드를 탈 때, 메인 스레드에서의 기능을 쓰지 못한다는 것(!!)

 

여러 방식으로 스크립트를 동작시켜봤지만 모두 안 되었다.

다른 방식으로 버벅임을 잡아야겠다.

 

 

유니티 허브에서 프로젝트를 클릭했을 때 열리지 않을 때가 있습니다.

그럴 때 여러 해결방법이 있겠지만 제가 해결한 방법은 라이센스를 갱신하는 것이었습니다.

아마 그 때 안 됐던 이유가 만료날짜가 얼마 안 남아서 그랬었던게 아닐까 싶습니다.. --;

 

 

 

 

 

사람모양 아이콘을 클릭하면 리스트가 나옵니다.

Manage licenses 를 클릭해줍니다.

 

 

 

 

 

리프레쉬를 눌러서 라이센스를 새로 갱신해줍니다.

라이센스의 날짜가 바뀐걸 확인할 수 있습니다

이후 다시 프로젝트를 실행시키면 프로젝트가 켜집니다.

 

버튼을 누르면 오브젝트의 색이 변하도록 할 것이다.

 

 

 

 

맨 처음 하이어라키 창에서 대상이 될 큐브 오브젝트를 생성해준다

 

 

 

캔버스를 생성한 뒤

 

 

버튼들도 생성해준다.

세 가지 색을 할 것이므로 세 개 만들어준다.

 

이렇게 배치하였다.

이제 색을 바꿀 때 쓸 머테리얼들을 만들것이다.

 

프로젝트 창으로 가서 빈 공간에 우클릭을 한 뒤

 Create - Material을 눌러서 머테리얼을 생성해준다.

 

 

 

 

 

 

머테리얼을 누른 뒤 색을 선택한다.

 

 

이런식으로 세 개의 머테리얼을 생성하였다.

 

 

 

 

 

이제 스크립트를 하이어라키 창에 Change Color를 생성해서 오브젝트에 걸어준다.

스크립트를 바로 Change Color에 드래그앤 드랍해도 되고,

Change Color 오브젝트를 눌러서 AddComponent를 누른뒤 이름을 검색해 찾아서 추가해도 된다.

스크립트는 머테리얼 생성과 마찬가지로 프로젝트창에서 우클릭을 한 뒤 생성해주면 된다.

기존에 있던 스크립트 내용을 지우고 아래의 스크립트를 넣어준다.

 

 

 

using UnityEngine;


public class ChangeColor : MonoBehaviour
{
    // 색깔 바꾸려는 오브젝트							
    public GameObject target;

    // 색깔들 등록							
    public Material grey;
    public Material purple;
    public Material yellow;

    public void ColorChange(string _color)
    {
        if (_color == "grey")
        {						
            target.GetComponent<MeshRenderer>().material = grey;
        }
        else if (_color == "purple")
        {
            target.GetComponent<MeshRenderer>().material = purple;
        }
        else if (_color == "yellow")
        {
            target.GetComponent<MeshRenderer>().material = yellow;
        }
    }
}

 

 

 

이제 오브젝트들을 제 자리에 넣어주자.

바꾸려는 대상 오브젝트를 Target에,

바꾸려는 색깔 머테리얼을 각각의 이름에 넣어준다.

 

 

 

 

이제는 버튼에 기능을 걸어줄 시간이다.

하이어라키창에 생성해둔 Canvas - Button으로 들어간 뒤 기능을 걸어준다.

 

위에 표시해둔 순서대로

1. + 버튼을 누른 뒤

2. ChangeColor 오브젝트를 드래그앤 드랍해주고

3. 이름을 써준다. 참고로 이름은

 

 

위에 동그라미가 쳐진곳에 적힌 이름이다.

만약 이름을 바꾸고싶다면 ChangeColor로 들어가서 동그라미가 쳐져있는 부분의 이름을 바꾸면 된다.

스크립트의 이름과 3번에 적힌 이름과 동일해야 한다.

 

이렇게하면 맨 처음의 그림과 같은 결과가 나오게 된다.

 

끝.

 

 

 


 

 

응용. 상어 색깔 바꾸기

더보기

 

 

							
using UnityEngine;							
							
							
							
public class ChangeColor : MonoBehaviour							
{							
    // 색깔 바꾸려는 오브젝트							
    public GameObject target;							
							
    // 색깔들 등록							
    public Material grey;							
    public Material purple;							
    public Material yellow;							
							
    public void ColorChange(string _color)							
    {							
        if(_color == "grey")							
        {							
            // GetComponent<Material>() 로 들어가면 안 된다.							
            target.GetComponent<SkinnedMeshRenderer>().material = grey;							
        }							
        else if (_color == "purple")							
        {							
            target.GetComponent<SkinnedMeshRenderer>().material = purple;							
        }							
        else if (_color == "yellow")							
        {							
            target.GetComponent<SkinnedMeshRenderer>().material = yellow;							
        }							
    }							
}

 

 

 

 

 

 

 

https://youtu.be/7Vgb8MoWIq8

데브곰돌의 엔드리스 러너 만들기

 

 

 

오브젝트 세팅

<Player>

Sprite Renderer, Animator, Player Controller, Capsule Collider2D, Rigidbody 2D

<GroundHolder>

 

<SpawnManager>

 

<GameManager>

 

<Canvas>

<Score>

Text

 

 

<Button>

 

<BestScore>

Text

 

 

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    bool isJump = false;
    bool isTop = false;
    public float jumpHeight = 0;
    public float jumpSpeed = 0;

    Vector2 startPosition;
    Animator animator;

    void Start()
    {
        startPosition = transform.position;
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        if (GameManager.instance.isPlay)
            animator.SetBool("run", true);
        else
            animator.SetBool("run", false);


        if(Input.GetMouseButtonDown(0) && GameManager.instance.isPlay) // isPlay모드일 때 발동하도록., // 마우스입력감지
        {
            isJump = true;
        }
        else if(transform.position.y <= startPosition.y)
        {
            isJump = false;
            isTop = false;
            transform.position = startPosition;
        }


        if(isJump) //GetmouseButtonDown은 마우스 클릭시 한 번만 인식하므로 판정오류를 없애기 위해 바로 코드를 적지 않는 것.
        {
            if(transform.position.y <= jumpHeight - 0.1f && !isTop)
            {
                transform.position = Vector2.Lerp(transform.position, new Vector2(transform.position.x, jumpHeight), jumpSpeed * Time.deltaTime);
            }
            else
            {
                isTop = true;
            }

            if(transform.position.y > startPosition.y && isTop)
            {
                transform.position = Vector2.MoveTowards(transform.position, startPosition, jumpSpeed*Time.deltaTime);
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.CompareTag("Mob"))
        {
            GameManager.instance.GameOver();
        }
    }
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 몹 프리팹이 활성화되면 화면 우측에서 시작해서 화면 좌측을 넘어가면 다시 비활성화 되는 코드
public class MobBase : MonoBehaviour
{
    public float mobSpeed = 0;
    public Vector2 StartPosition;

    private void OnEnable()
    {
        transform.position = StartPosition;
    }

    void Update()
    {
        if(GameManager.instance.isPlay)
        {
            transform.Translate(Vector2.left * Time.deltaTime * GameManager.instance.gameSpeed);

            if (transform.position.x < -6)
            {
                gameObject.SetActive(false);
            }
        }
    }
}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RespawnManager : MonoBehaviour
{
    public List<GameObject> MobPool = new List<GameObject>();
    public GameObject[] Mobs;
    public int objCnt = 1;

    void Awake()
    {
        for(int i = 0; i < Mobs.Length; i++)
        {
            for(int q = 0; q < objCnt; q++)
            {
                MobPool.Add(CreateObj(Mobs[i], transform));
            }
        }
    }
     void Start()
    {
        GameManager.instance.onPlay += PlayGame;
    }

    void PlayGame(bool isplay)
    {
        if (isplay)
        {
            for(int i = 0; i < MobPool.Count; i++)
            {
                if (MobPool[i].activeSelf)
                    MobPool[i].SetActive(false);
            }
            StartCoroutine(CreateMob());
        }
        else
            StopAllCoroutines();
    }

    IEnumerator CreateMob()
    {
        yield return new WaitForSeconds(0.5f);
        while(GameManager.instance.isPlay)
        {
            //MobPool[Random.Range(0, MobPool.Count)].SetActive(true);
            MobPool[DeactiveMob()].SetActive(true);
            yield return new WaitForSeconds(Random.Range(1f, 3f));
        }
    }

    int DeactiveMob()
    {
        List<int> num = new List<int>();
        for(int i = 0; i < MobPool.Count; i++)
        {
            if (!MobPool[i].activeSelf) // 비활성된 녀석을 찾아 활성화시킨다.
                num.Add(objCnt);
        }
        int x = 0;
        if (num.Count > 0)
            x = num[Random.Range(0, num.Count)];
        return x;
    }

    GameObject CreateObj(GameObject obj, Transform parent)
    {
        GameObject copy = Instantiate(obj);
        copy.transform.SetParent(parent);
        copy.SetActive(false);
        return copy;
    }
}

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GroundScroller : MonoBehaviour
{
    public SpriteRenderer[] tiles;
    public Sprite[] groundImg;
    public float speed;


    void Start()
    {
        temp = tiles[0];
    }
    SpriteRenderer temp;

    void Update()
    {
        if(GameManager.instance.isPlay)
        {
            for (int i = 0; i < tiles.Length; i++)
            {
                if (-5 >= tiles[i].transform.position.x) // 타일 x좌표가 -5보다 작으면,
                {
                    // 가장 뒤에 있는 타일을 검색하는 방법은 변수를 하나 두고 반복문과 배열을 이용하여 현재 타일 변수보다 x가 크면 현재 타일을 초기화해주면 된다.
                    for (int q = 0; q < tiles.Length; q++)  
                    {
                        if (temp.transform.position.x < tiles[q].transform.position.x)
                        {
                            temp = tiles[q];
                        }
                    }
                    tiles[i].transform.position = new Vector2(temp.transform.position.x + 1, -0.3f);
                    tiles[i].sprite = groundImg[Random.Range(0, groundImg.Length)];
                }
            }

            for (int i = 0; i < tiles.Length; i++)
            {
                tiles[i].transform.Translate(new Vector2(-1, 0) * Time.deltaTime * GameManager.instance.gameSpeed);
            }
        }
    }
}

 

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class GameManager : MonoBehaviour
{
    #region instance
    public static GameManager instance;
    private void Awake()
    {
        if(instance != null)
        {
            Destroy(gameObject);
            return;
        }
        instance = this;
    }
    #endregion

    public delegate void OnPlay(bool isplay);
    public OnPlay onPlay;

    public float gameSpeed = 1;
    public bool isPlay = false;
    public GameObject playBtn;

    public Text bestScoreTxt;
    public Text scoreTxt;
    public int score = 0;

    private void Start()
    {
        bestScoreTxt.text = PlayerPrefs.GetInt("BestScore", 0).ToString();
    }

    IEnumerator AddScore()
    {
        while(isPlay)
        {
            score++;
            scoreTxt.text = score.ToString();
            gameSpeed = gameSpeed + 0.01f;
            yield return new WaitForSeconds(0.1f); // 0.1초마다 스코어를 1씩 더해준다.
        }
    }

    public void PlayBtnClick()
    {
        playBtn.SetActive(false);
        isPlay = true;
        onPlay.Invoke(isPlay);
        score = 0;
        scoreTxt.text = score.ToString();
        StartCoroutine(AddScore()); //코루틴 시작!
    }
    public void GameOver()
    {
        playBtn.SetActive(true);
        isPlay = false;
        onPlay.Invoke(isPlay);
        StopCoroutine(AddScore());
        if(PlayerPrefs.GetInt("BestScore", 0) < score)
        {
             PlayerPrefs.SetInt("BestScore", score);
            bestScoreTxt.text = score.ToString();
        }
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

위의 다섯 이미지는 누를 때 소리가 나는 버튼이다.

씬도 넘어간다.

 

그런데,

 

어떤 버튼에서는 소리가 나지만 어떤 버튼에서는 소리가 나지 않는 문제가 발생했다.

같은 형식의 스크립트이고, 오브젝트에 제대로 삽입도 되었는데 왜 그럴까?

다시 하나하나 수정을 하던 도중 씬의 이동과 관련이 있지 않을까 하는 생각이 들었다.

무거운씬으로 넘어가는 버튼은 비교적 소리가 끝까지 잘 들렸지만

상대적으로 가벼운씬으로 넘어가는 버튼은 소리가 끊겼기 때문.

씬의 변환과 연관이 있다고 생각했기에 오브젝트를 살릴 방법을 찾았다.

 

 

 

DontDestroyOnLoad();

 

처음에는 플레이하는 중이면 살리기로 했다.

그러나 안타깝게도 저렇게 하면 소리가 걸려있는 버튼은 구제(?)하지 못한다.

 

 

버튼의 Inspector창이다.

 

음악이 들어있는 오브젝트이다.

 

버튼을 눌러서 음악 재생인 상태인들, 버튼 오브젝트나 음악이 들어있는 오브젝트 둘 다

PlayOnAwake의 박스에 체크가 되지 않는다.

 

 

이렇게 쓰거나,

 

 

혹은 이렇게.

 

 

 

단점은, 이렇게 하면 씬을 넘나들면서 하이어라키 창에 쓰지 않는 오브젝트가 계속 쌓이게 된다.

적당히 없애주도록 하자..

버튼을 눌렀을 때 버튼사운드매니저의 디스트로이 스크립트를 활성화 시키는것으로 짜면

해결될 것 같다.

 

 

그리고 또 하나의 주의사항이 있다.

* 내가 DonDestroyOnLoad하려는 오브젝트가 자식 오브젝트여서는 안 된다.

 

 

 

 

 

 

 

 

 

 

 

https://docs.unity3d.com/kr/530/ScriptReference/Object.DontDestroyOnLoad.html

유니티에서는 AudioSource 컴포넌트를 스크립트로 제어할 수 있다.

 

프로젝트를 만들던 중,

코루틴으로 지연시킨 후 플레이하고 싶은 일이 생겼다.

이런 경우 컴포넌트에 delay 기능이 없으므로

스크립트로 재생 시점을 조정.

 

위처럼 스크립트를 작성해주면 내가 설정한 시점에 새로운 컴포넌트가 추가된다.

AddComponent로 하면 기존에 AudioSource컴포넌트가 붙어 있었어도

새로운 AudioSource컴포넌트가 만들어진다.

 

새로 만들어지는 것이기 때문에

컴포넌트를 추가한 뒤 클립을 이용하여

재생하고 싶은 오디오 파일을 오디오 클립에 넣는 스크립트도 같이

짜주어야 한다.

안 그럼 클립에 아무것도 없어서 소리가 안 난다.

(재생할게 없는 상태이니..)

 

 

 

그렇다면 기존에 세팅해둔 AudioSource 컴포넌트를 원하는 때에

작동하게 하려면 어떻게 해야할까?

컴포넌트에 미리 세팅을 해둔 후 컴포넌트를 불러와서 클립을 재생하면 된다.

 

 

 

스크립트로 오디오 소스를 건드리는 경우에는

내 의지와는 상관없이 재생되는것을 방지하기 위해 체크를 해제해야 한다.

 

 

 

 

 

Public Functions

GetCustomCurve AudioSource의 아웃풋 AudioMixer를 설정합니다.
GetSpatializerFloat Reads a user-defined parameter of a custom spatializer effect that is attached to an AudioSource.
Pause 재생중인 clip을 일시정지 합니다.
Play 일정한 딜레이를 갖게 하여 clip을 재생합니다.
PlayDelayed 초 단위로 지정된 지연에 clip을 재생합니다. 사용자는 44.1kHz의 참조 레이트와 관계하고 있는 샘플의 지정된 딜레이를 인수로 한 오래된 Play(delay) 함수 대신 이 함수를 사용하는 것을 추천합니다.
PlayOnDualShock4 Enable playing of audio source though a specfic DualShock4 controllerEnable playing of audio source though a specfic DualShock4 controller.
PlayOneShot AudioClip을 재생하며, volumeScale에 의해 AudioSource 볼륨을 스케일합니다.
PlayScheduled Plays the clip at a specific time on the absolute time-line that AudioSettings.dspTime reads from.
SetCustomCurve 현재의 오디오 소스(Audio source)에 대한 도플러효과 범위(Doppler scale)를 설정합니다.
SetScheduledEndTime Changes the time at which a sound that has already been scheduled to play will end. Notice that depending on the timing not all rescheduling requests can be fulfilled.
SetScheduledStartTime Changes the time at which a sound that has already been scheduled to play will start.
SetSpatializerFloat Sets a user-defined parameter of a custom spatializer effect that is attached to an AudioSource.
Stop clip의 재생을 정지합니다.
UnPause 이 AudioSource에 대해 일시정지된 재생상태를 해제합니다.

https://docs.unity3d.com/kr/530/ScriptReference/AudioSource.html

 

폴더정리하다 전에 캡쳐해뒀던 자료를 찾았다.

 

시험 전에 기출문제 찾으려 구글링했었는데 못 구했던게 생각나서

 

하드에 있던 자료 정리중에 올려본다.

'일상' 카테고리의 다른 글

Hololens2 특강  (0) 2021.11.11
Poiesis with AI  (0) 2021.11.11

 

늘어나는 말풍선이다.

글자 크기에 맞춰 매번 이미지를 수정할 수 없기 때문에 필요한 기능.

 

 

 

스프라이트 에디터에서 늘어날 부분을 정해줘야 한다.

초록색 선으로 정해주자.

만약 스프라이트 에디터에서 미리 수정을 하지 않으면

 

결과물이 1번처럼 되지 않고 2번처럼 되어버린다.

 

 

 

 

스프라이트 에디터가 없으면 Packages:Unity Registry에서 2D Sprite를 다운받아야 한다.

 

편집한 스프라이트를 이미지에 넣어준다.

 

 

두 컴포넌트를 추가해줘야 한다.

Padding으로 크기를 조정하고

Control Child Size를 체크한다.

Content Size로 따를 사이즈를 바꿔준다.

 

 

 

-----------------

 

Vertical Layout Group

수직 레이아웃 그룹 컴포넌트는 자식 레이아웃 요소를 쌓습니다. 요소의 높이는 다음 모델에 따라 각각 최소, 선호, 가변 높이를 기준으로 결정됩니다.

  • 모든 자식 레이아웃 요소의 최소 높이를 합산하고 요소 간의 간격도 더합니다. 결과값이 수직 레이아웃 그룹의 최소 높이입니다.
  • 모든 자식 레이아웃 요소의 선호 높이를 합산하고 요소 간의 간격도 더합니다. 결과값이 수직 레이아웃 그룹의 선호 높이입니다.
  • 수직 레이아웃 그룹이 최소 높이이거나 더 작은 경우 모든 자식 레이아웃 요소도 최소 높이를 가집니다.
  • 수직 레이아웃 그룹이 선호 높이에 가까워질수록 각 자식 레이아웃 요소도 선호 높이에 가까워집니다.
  • 수직 레이아웃 그룹이 선호 높이보다 크면 사용 가능한 추가 공간을 자식 레이아웃 요소에 각각의 가변 높이에 따라 비례적으로 분배합니다.

https://docs.unity3d.com/kr/2018.4/Manual/script-VerticalLayoutGroup.html

 

설명

콘텐츠 크기 피터는 자체 레이아웃 요소의 크기를 제어하는 레이아웃 컨트롤러의 기능을 수행합니다. 크기는 게임 오브젝트의 레이아웃 요소 컴포넌트에서 제공하는 최소 또는 기본 크기에 따라 결정됩니다. 레이아웃 요소는 Image 또는 Text 컴포넌트이거나, 레이아웃 그룹이거나, Layout Element 컴포넌트일 수 있습니다.

사각 트랜스폼의 크기를 콘텐츠 크기 피터 등으로 조정하는 경우 피벗을 중심으로 크기가 조정되므로 피벗을 사용하여 크기 조정 방향을 제어할 수 있다는 점을 기억하면 유용할 수 있습니다.

예를 들어 피벗이 중앙에 있는 경우 콘텐츠 크기 피터에서 사각 트랜스폼을 모든 방향으로 균등하게 확장합니다. 그리고 피벗이 왼쪽 상단 모서리에 있는 경우 콘텐츠 크기 피터에서 사각 트랜스폼을 오른쪽 아래 방향으로 확장합니다.

 

https://docs.unity3d.com/kr/2019.4/Manual/script-ContentSizeFitter.html

 

 

 

홀로렌즈2 특강을 받고왔다.

사실상 설치가 강의의 반을 차지했다.

전에 홀로렌즈2를 했을때랑 설치과정이 달라졌다.

강사님도 매번 새로 업데이트가 되기 때문에 앞으로 어떻게 될지 모른다고 했다.

언제 바뀔지 모른다고..

유니티가 많이 지원을 한다고 했다. 그러니 이렇게 최적화하거나 툴 이용하는 데서 변화도 많고 적응도 많고 그런것이겠지?

아직1년도 채 안 됐는데 진짜 빨리 바뀌는구나..,

 

홀로렌즈는 게임씬에서 테스트한것이 실제 홀로렌즈상에서도 같기 때문에

둘의 차이 조정이 거의 불필요할 정도라고했다.

 

MRTK의 인터페이스도 바뀌었다.

 

홀로렌즈는 장비는 고가인데 비해 성능은 높지 않다고.. ㅜㅜ 나도 저번 팀 프로젝트에서 느꼈다.

사실상 배터리가 많은 부분을 차지하는데, 절반 정도를 배터리 사이즈라고 생각하면 된다고 하셨다.

 

 

 

 

 

 

나는 이런 일일 특강에 참여하는게 꽤 도움이 된다고 생각한다.

왜냐하면, 변화 빠른 it이고

특강에서는 기존과 다른 새로운 정보, 기존의것이 어떤식으로 변화했는지를 알려주기 때문이다.

'일상' 카테고리의 다른 글

Unity Associate 자격증시험 예상문제(유니티 시험)  (0) 2021.11.17
Poiesis with AI  (0) 2021.11.11

 

바밤.

 

여기 다녀왔다.

 

이름에서 보이듯 AI위주로 러닝머신등의 기술을 이용한 콘텐츠들을 전시해둔곳이었다.

나는 XR쪽이지만 기술 트렌드가 궁금하기도 했고, 폭 넓게 알아두면 나중에 도움(팀플, 향후 이해도)이 될 것 같아서 가봤다.

내가 속한 스터디원이 참여하기도 했고.

 

 

 

게임을 마우스나 키보드로 조정하는 대신 음성으로 명령해서 게임 캐릭터를 조종하는 콘텐츠도 있었다.

음성 명령을 계속 모아서 가라. 가줘. 가. 이런 의미는 같지만 표현은 다른 음성들에 대한 정보를 모아서

명령을 수행한다는 그런 콘텐츠였다.

실제로 플레이 해봤는데,

나는 심시티나 롤러코스터 타이쿤에 쓰면 더 적합할 것 같아서 그렇게 말했다.

RPG게임을 조종하기엔 음..,

마우스라던가 키보드로 느끼는 타격감(대리만족이지만)을 느끼지 못하고 그저 영상만을 시청하게 되기 때문에.

그랬더니 좋은 아이디어얌! 이라고 해서 뿌듯했다.

 

 

 

사진이 이상하게 나오긴 했지만, 사진(매체1) + 문장(단어와 동사등이 결합된)으로 미술작품을 만들어내는 작품이었다.

결합의 정도도 있어서 정도별로 다른 느낌의 작품이 탄생한다.

작품은 박물관에 전시되어있었는데,

VR 기술을 같이 이용하면 VR로 박물관 내부를 돌아다니며 인공지능으로 만든 작품을 관람할 수 있을 것 같았다.

 

 

 

 

 

위의 작품은 유저가 보기만 하는 것이지만

아래의 작품은 상호작용이 가능했다.

마이크에 대고 말하면 우체통이 대답한다.

저 편지 가져가는건줄알고 뜯....

영상촬영도 해주고, 촬영된 영상이 저장되기도 한다고...

 

 

 

 

그림을 그리면 그림을 읽고 곡을 연주해주는 콘텐츠이다.

QR코드로 그림을 받거나 음악을 받을 수 있다고 한다.

저건 내가 그린 어몽어스이다.

 

 

 

 

 

 

 

 

메타버스 안에서는 사람들이 도덕적으로 해이해질것이라고 생각,

메타버스 내에서 행동을 할 때 유저들의 뇌파를 기록한다. 라고 말했었는데,

지금은 메일로 가입하기 기능 정도만 구현된 상태였다.

논문을 쓰셨던데 어디 올라가진 않았다고..

그래서 볼 수는 없다.

 

 

 

 

 

서울예대이름도 보였는데,

미디어아트쪽에서 참여한 것 같았다.

이제는 미디어 아트가 인공지능을 결합하여 저런것들을 만들어내는구나..

싶었다.

더 이상 프로그래밍이 개발자들만의 기술이 아니라 무언가를 표현하는 수단이 된 것 같았다.

'일상' 카테고리의 다른 글

Unity Associate 자격증시험 예상문제(유니티 시험)  (0) 2021.11.17
Hololens2 특강  (0) 2021.11.11

+ Recent posts