1. 자동으로 회전하는 게임오브젝트 만들기


플레이어의 터치나 드래그를 통한 조작이 아니라 자동으로 회전하고 싶다면, 간단하다.


update() 함수에서 프레임마다 호출해주면 된다.


transform.Rotate(0, ySpeed, 0);


이렇게 하면, 해당 오브젝트가 y축으로 자동 회전하게 된다.


균일한 속도로 돌리고 싶다면 Time.deltaTime()을 곱해주면 된다.


transform.Rotate(0, ySpeed * Time.deltaTime(), 0);



2. 모바일에서 터치를 이용해 게임오브젝트 회전하기


y축 방향으로 좌우 360도 회전을 하고 싶다면 다음과 같이 하면 된다.


foreach (Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Moved)
{
transform.Rotate(0, -touch.deltaPosition.x, 0);
}
}



이렇게 하면, 모바일 터치를 읽어들여, 움직일 때 회전을 하게 된다.



http://madewithunity.blogspot.kr/2015/09/how-to-rotate-object-with-unity-3d.html

Posted by sungho88
,

http://kimseunghyun76.tistory.com/194

http://programmingsource.tistory.com/18 


유니티에서도 안드로이드와 같이 생명 주기가 존재한다.


생명 주기(Life Cycle)이란, 유니티 내부에서 알아서 프로젝트 시작부터 종료까지 진행하는 흐름이다.


즉, 사용자가 직접 만들지 않아도 자동으로 호출되는 메소드가 존재한다.


예를 들면 Awake()와 Start() Update() 등등... 이 함수의 호출 흐름을 말한다.


먼저, 4가지 함수만 알아보자.

 

호출 순서


1. Awake() 

 

- 스크립트가 실행될 때 단 한번만 호출된다.

- 모든 오브젝트가 초기화된 후에 호출되기 때문에 GameObject.Find, GameObject.FindWithTag 등의 명령어들을 

   안전하게 사용할 수 있다.

- Awake 함수는 항상 Start() 함수 이전에 호출되므로 초기화 순서를 정할 수 있게 된다.

- 코루틴(Coroutine) 사용이 불가능하다.


2. OnEnable()


- 인스펙터뷰에서 게임오브젝트를 활성화/비활성화를 체크한다. 즉, 체크(활성화) 되었을 때 호출된다.

- 만약, 게임오브젝트를 껐다가 다시 켜면, Start()는 불리지 않으므로 작동이 되지 않는다.

- 활성화/비활성화를 사용하고자할 때, 이 함수에 활성화되었을 때 일어날 코드를 넣는다.


3. Start()


- Update() 함수가 호출되기 전에 한번만 호출된다.

- 다른 스크립트의 모든 Awake()가 실행이 끝난 이후에 실행된다.

- 스크립트가 활성화되어 있어야만 호출되어 실행된다.


4. Update()


- 매 프레임마다 호출되는 함수이며, 게임 로직에 핵심적으로 사용된다.

- 스크립트가 활성화 되어있어야 사용이 가능하다.

- 일시적으로 사용하지 않으면 불필요하게 성능저하 발생 가능성이 커진다.(매 프레임 반복 실행이므로 1초에 수십번..)



Posted by sungho88
,

엄청난 사실하나 알려드리려고 합니다.


왠만하면이 아니라 웬만하면이 표준어라고 합니다.


놀랍지 않습니까? 


...저만 놀란건가요!? 


왠만하면으로 알고 있었는데...


글쓸 일이 없으니 말할때는 모르던 국어.


한국인이니 한국어는 알아야하지 않겠습니까?


ㄴㅔ이버 사전 한 번 봅시다!




Posted by sungho88
,

매번 아무 생각없이 사용하던 GameObject와 gameObject의 차이점에 대해 생각해보게 되었다.


확실하게 알고 넘어가자.


GameObject의 특성


- GameObject는 클래스이다. 객체가 아니다.


- Hierarchy 창에 계층구조를 이루는 게임 오브젝트 객체들을 의미한다.


- 유니티에서 기본적으로 제공되는 객체는 GameObject가 기본이다.


- 게임오브젝트는 게임을 구성하는 모든 요소(눈에 보이지 않는 카메라, 빛 포함)를 뜻한다.


- 스크립트에서 GameObject를 쓰는 이유는 다른 게임오브젝트를 호출하기 위함이다.



gameObject의 특성


- gameObject는 클래스가 아니다. 객체이다.


C# 스크립트 생성후 유니티 Hierarchy내 임의의 게임오브젝트로 스크립트를 Add Component하는데,  

이 과정은 일반적인 객체 생성 과정인  GameObject gameObject = new GameObject(); 

명령어를 자동 선언한 것이나 마찬가지이므로 선언하지 않아도 gameObject는 스크립트로 바로 참조가 가능하다.


쉽게 말하면, 해당 컴포넌트에 할당된 자기 자신이다.


만약 Player라는 게임오브젝트 내 스크립트에 gameObject를 썼다면 Player의 컴포넌트를 조작하는데 사용될 것이다.


- 스크립트에서 gameObject를 사용하면, 해당 게임 오브젝트를 호출한다.


좀 더  디테일한 차이점이 있을 것 같지만, 일단 간략하고 대표적인 차이점은



어떤 GameObject에 Attached된 스크립트 안의 


gameObject는 항상 '해당 GameObject 자신'이고, 

GameObject는 '해당 GameObject 자신'일지 아닐지 모른다.


좀 더 정리가 필요하다.. 아직 명확하지 않다. 뭔가 헷갈린다.

Posted by sungho88
,

초기화를 하지 않았든, 어쨋든 null이 발생할 가능성이 높다.


널 체크는 간단하지만 중요하다. 널 체크를 꼭 해주자. 방법은 다음과 같다.


만약, Image myImage;으로 선언을 한다면,


if (myImage != null)

   XXXXXXXXX


도 물론 가능하지만, 더욱 간단하게 체크할 수도 있다.


if (myImage)

   XXXXXXXXX


이렇게 해도 된다. 


주의할 점 : null이라면, 이 아니라 null이 아니라면 이 조건값이다.


반대로, null일때 뭔가를 해주고 싶다면 부정연산자 !를 붙여서


if (!myImage)

   XXXXXXXXX


로 작성해야 에러가 발생하지 않는다.


다시한번 말하지만, 


!을 사용하지 않는다 = 널이 아닐때.

!을 사용한다 = 널일 때.




Posted by sungho88
,

using System.Collections;

using System.Collections.Generic;

using UnityEngine;


public class MaterialTest : MonoBehaviour {

public SkinnedMeshRenderer skin;

// Use this for initialization

void Start () {

  skin.GetComponent<SkinnedMeshRenderer>().material.color = Color.black;  // 첫 번째 방법


for (int i = 0; i < 2; i++) {                                                                                    // 두 번째 방법

skin.GetComponent<SkinnedMeshRenderer> ().materials [i].color = Color.black;

}

}

}



1. 첫번째 방법  


skin.GetComponent<SkinnedMeshRenderer>().material.color = Color.black;

쉽게 말하면, material이 한 개일 경우에 이렇게 사용한다. 그냥 material을 호출하면 자동으로 인식되는 경우이다.


2. 두번째 방법


for (int i = 0; i < 2; i++) {                                                                                    // 두 번째 방법

skin.GetComponent<SkinnedMeshRenderer> ().materials [i].color = Color.black;

}


쉽게 말하면, material이 여래 개일 경우에 이렇게 사용한다. 


유니티에서는 보통 materials라 나오며 배열로 표기된다. 

 

이럴 경우에는 for문을 사용해서 material의 갯수만큼 반복하며 material을 조작할 수 있다.


위 코드의 경우 매티러얼이 2개이므로 materials [0] 과 materials [1]을 각각 반복하였다.


이상으로 스크립트에서 material을 사용하는 방법에 대해 알아봤다.

Posted by sungho88
,
JTBC 서울 마라톤 영상 촬영 모델 모집
중앙서울마라톤이
JTBC서울마라톤으로 이름이 변경되었다고 합니다.
 
@ 촬영일시 : 2018년 04월 27일 금요일
                     오전09시 부터 ~ 20시까지
                     (중식 석식 제공)
 
@ 장소 : 여의도 일대

@ 모집인원 : 00명

@ 페이 및 혜택 :
-일반 : 10만원 + JTBC서울마라톤 참가권
-코스프레 : 15만원 + JTBC서울마라톤 참가권
(* JTBC서울마라톤 참가권 지급은 될수도 있고 안될 수도 있는 상황입니다)

@ 촬영복장 : 러닝 복장 또는 코스프레
-코스프레 복장의 경우 저작권 없는 복장으로 가져와 주시면 감사하겠습니다
ex)바나나,중동석유부자,공룡풍선옷 등

@ 문의 : 왕모세(010-5357-1579)

@ 참가를 원하시면 아래 카카오톡 오픈채팅방으로 들어오시기 바랍니다
https://open.kakao.com/o/grpzi5K
Posted by sungho88
,

버튼에 애니메이션을 실행(Play)시킬 때 발생하는 문제가 하나 있었다.


같은 버튼을 계속 누를 때 최초 1회만 애니메이션이 재생되고, 그 이후 두번 다시 Play되지 않은 문제였다.

 

그래서 틀렸을 때 흔들리는 애니메이션이 1번만 보여지고 그 이후는 무반응이므로 뭔가 어색하게 되었다.


오브젝트를 껐다가 켜야하나 생각도 해보고 구글을 찾아봤지만 한국어 검색으로는 비슷한 문제가 발견되지 않았다.


그래서 형편없는 영어 실력으로 영어 검색을 시작했다.


검색어 : unity animator play once reset


그결과 유니티 커뮤니티에서 어떤 한 외국인님이 나와 완전히 동일한 문제를 질문했고, 답을 얻을 수 있었다.


생각보다 별 것 아니었다. 몰라서 못 쓴 것이지만,,]


내가 사용했던 Play("AnimationName"); 에서 확장된...아니 오버로딩된



public void Play(string stateName, int layer = -1, float normalizedTime = float.NegativeInfinity);


을 사용하라고 한다.



아래 코드가 내가 사용한 기본적인 코드이다. 이렇게 하면 플레이는 된다.


buttonObject.GetComponent<Animator>().Play("ButtonWrong");


하지만,


buttonObject.GetComponent<Animator>().Play("ButtonWrong", -1, 0f);



첫 번째 매개변수 : stateName

두 번째 매개변수 : layer

세 번쨰 매개변수 :normalizedTime


첫 번쨰 매개변수로는 Play할 애니메이션 state의 이름을 적는다.


두 번째 매개변수로는 layer를 설정한다. -1일 경우 첫 state를 재생한다.


세 번째 매개변수로는 normalizedTime를 적는다.


normalizedTime란,


표준화된(normalized) 애니메이션 시간아다. 


값 1은 애니메이션의 끝을 의미하며 값 0.5는 애니메이션의 중간을 의미한다.


Posted by sungho88
,

버튼을 눌렀을 때, 버튼음을 집어넣었다.


그런데, 버튼을 빠르게 누르면 누른 횟수대로 사운드가 재생된다.


어떻게 이 문제를 해결할까?


1. PlayOneShot()함수 앞에 Stop()함수를 먼저 실행한다.


--> 안 된다. 짧아서 그런지 몰라도 .


매우 간단하게 해결 할 수 있다.


바로,


isPlaying을 잘 사용하면 된다.


public AudioSource soundSource;
public AudioClip[] sound;

if (soundSource && sound[3])
if (soundSource.GetComponent<AudioSource>().isPlaying) return;
else soundSource.GetComponent<AudioSource>().PlayOneShot(sound[3]);


핵심은 isPlaying을 사용하는 것이다.


만약(if)현재 플레이 중이라면 return 즉, 아무것도 진행하지 말라는 의미이며,


그렇지 않다면(=플레이 중이 아니라면else) PlayOneShot을 사용하여 1회 플레이하라는 의미이다.


이렇게하면 버튼을 미친듯이 눌러도 이벤트는 발생하지만 isPlaying에 막혀 사운드는 출력되지 않는다.


이상으로 버튼 사운드 중복될 때 해결 방법을 알아봤다.

Posted by sungho88
,


고려산 위치는 강화도 중심에 있다.


마니산이 유명한데, 고려산도 진달래로 유명하다.




2018년 04월 14일 ~ 04월 22일까지 진행된다.


진달래꽃보러 사당역에 07시 도착해서 버스를 타고 이동했다.


강화도... 거리 비해 많이 걸렸다. 강화도 초입부터 차가 막히기 시작했다.


어쨋든 등산 시작!


좀 실망했다. 진달래가 없어! 앙상한 가지만 잔뜩. 실망하며 1시간 올라갔다.


오...정상엔 진달래가 나름 많이 피어있었다. 그리고 진달래와 함께 사람들이 비례적으로 나타나기 시작했다.


세 갈래길에서 병목현상이 일어나기 시작했다. 와 사람 사람 이렇게 사람 많은 건 처음 봤다.


오 우...이게 축제의 현장인가~~~




쭉 그냥 이동하면 오래 안 걸리겠지만... 구경하고 사진찍느라 움직일 생각이 없다.


빠르게 이동할 생각도 없었기때문에 더 지연시키며 천천히 걸었다.


빠르게 빡시게 등산하려면 다른산을 추천한다.


이제 진달래 축제인만큼 사진 투척~~~




우와 우와하면서 만족하고 있는데... 몇 번 온 사람이 이건 많이 핀 것도 아니라고 한다...


난 이정도만 봐도 만족하므로 재밌었다.


산행을 했으니 먹으러 출발~


강화도에 왔으니 강화도 풍물시장에 가보자~


벤뎅이 회가 유명하다고 하니 먹어보자. 벤뎅이~~


(벤뎅이 회)

(벤뎅이 무침)

벤뎅이 구이


각각 23,000원이지만, 세트로 먹으면 4인기준 50,000원에 먹을 수 있다!



마무리는 칼국수로!

Posted by sungho88
,