유니티 애즈달면 얼마 버는지 궁금해서 찾아봤는데

정보가 별로 없어서 돌아다니다가 유니티애즈 공식 블로그글을 발견했다.


아래는 유니티애즈 블로그의 Q&A글 일부


Q: 돈을 얼마나 벌수 있나요?

A: 수익은 여러가지 요소에 의해 결정됩니다. – 어떠한 플랫폼을 사용하는지(iOS or Android) 게임 사용자의 국가가 어디인지, 광고를 어디에 위치 시켰는지, 하지만 가장 중요한 요소는 게임 사용자의 수 입니다.

국가별 차이는 있을 수 있지만, 일반적으로 광고 영상 1000회 시작시(스킵광고 포함) 6~12$정도의 수익을 얻으실수 있습니다.

Q: adrequest는 0인데, 광고 노출은 있는 이유가 무엇인가요?

A: 샘플링의 이유로13번째 adrequest만 기록됩니다. 따라서 하루에 매우 소량의 adrequest가 있다면, 오직 13번째 adrequest만 통계에 집계됩니다.


적어도 13번은 봐야지 통계에 집계되고 1000번을 봐야지 10달러 쯤을 번다고 한다...


출처 : http://www.unityads.co.kr/?p=1143

블로그 이미지

stuban

ㅇ.ㅇ

,

유니티에서 코딩하면서 가장 좋아하는 기능중에 하나였던거 같다.

물론 유니티가 아니라 c#에서 쓰는거지만 어차피 난 유니티만 쓰니깐 유니티에서 쓰는법을 쓸거임


참고로 옛날에 썻던 네이버 블로그에 있던거 그대로 복붙함


c#에서 지원하는 xmlDocument클래스를 써서 xml데이터를 읽어올수 있는데

유니티에서 인스펙터로 끌어서 가지고 오려면 유니티에서 지원하는 TextAsset를 사용하면 된다.

물론 Resource.Load나 파일입출력으로 가지고 올 수도 있다.


아래는 랜덤한 철수를 뽑아오는 클래스다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
using System.Xml;//xml 네임스페이스 using하기
 
public class XMLTEST : MonoBehaviour {
 
    [SerializeField]
    private TextAsset xmlTxt;//텍스트 에셋으로 가지고온 xml파일
    private XmlDocument xmlDoc;//텍스트로 가져온 파일을 xml도큐먼트로 변환
    private void Start ()
    {
        //text를 XmlDocument에 맞게 변환
        xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(xmlTxt.text);
 
        Debug.Log(getName());
    }
    
    public string getName()
    {
        XmlNodeList nodes = xmlDoc.SelectNodes("Name/familyName/name");//랜덤한 성씨
        string name = nodes[Random.Range(0, nodes.Count)].InnerText;
        name += xmlDoc.SelectSingleNode("Name/lastName/name").InnerText;//하나의 이름
 
        return name;//이름 출력
    }
}
 
cs


xml 파일은 이렇게 되어있다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8" ?>
<Name>
  <familyName>
    <name></name>
    <name></name>
    <name></name>
    <name></name>
    <name></name>
    <name></name>
    <name>안</name>
    <name>조</name>
  </familyName>
  
  <lastName>
    <name>철수</name>
  </lastName>
</Name>
 
cs


System.Xml의 msdn 문서 : https://msdn.microsoft.com/ko-kr/library/system.xml(v=vs.110).aspx

XML에 대한 위키문서 : https://ko.wikipedia.org/wiki/XML 


블로그 이미지

stuban

ㅇ.ㅇ

,

유니티에서 좀 복잡한 데이터를 저장하고 싶을때 사용하면 좋은것

직렬화라는 기술인데 원리는 잘모르겠고 

이건 내가 옛날에 인터넷에서 언젠가 봐놓고 프로젝트에 썻던 코드를 예제처럼 꾸며놓은거다.

좀 무겁다고는 하는데 어차피 세이브를 프레임마다 하는건 아니니깐,,,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
//직렬화를 위한 네임스페이스들
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
 
[Serializable] // 직렬화할 클래스는 위에 이걸 써야함
public class Data
{    
    //클래스 안에 들어가는 데이터에 다른 클래스가 들어갈때는 그 클래스도 직렬화가능한 클래스 여야함(Vector 같은거 안됨)
    public string bang;    
    public int game;
    public bool right;
}
 
public class SaveMng : MonoBehaviour
{
 
///*
//
//*/
 
    public void Save(Data data)//세이브
    {
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();
        bf.Serialize(ms, data);
        
        string result = Convert.ToBase64String(ms.GetBuffer();
        PlayerPrefs.SetString("save", result);//변환해서 playerPrefs에 저장
    }
 
    public Data Load()//로드
    {
        Data data=null;
        string save = PlayerPrefs.GetString("save",null);
        
        if (!string.IsNullOrEmpty(save))//
        {
            var binaryFormatter = new BinaryFormatter();
            var memoryStream = new MemoryStream(Convert.FromBase64String(save));
            
            data = (Data)binaryFormatter.Deserialize(memoryStream);//형변환해서 사용
        }
        return data;
    }
}
cs


참고로 직렬화된 결과는 이런식으로 나옴

AAEAAAD/////AQAAAAAAAAAMAgAAAA9Bc3NlbWJseS1DU2hhcnAFAQAAAAREYXRhAwAAAAJkeQRnY

W1lBHN1Y2sBAAAIAQIAAAAKAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==

블로그 이미지

stuban

ㅇ.ㅇ

,

이렇게 된 스프라이트 시트 Resources.Load로 가지고 오기

1
2
Object[] sprites = Resources.LoadAll("baseBallBoyWooden");
sprRen.sprite = sprites[2as Sprite;

cs

배열의 첫번째는 나누기 전 모습 그 후부터는

배열에 담긴 순서대로 사용 ㅇㅇ


블로그 이미지

stuban

ㅇ.ㅇ

,

마우스 커서를 고정하는 방법이 Screen.LockCursor 인줄 알았는데 바뀌었는지 뭔지는 몰라도 변수가 없길래 다시 찾아보니 다른 방법이 있었다


1
2
Cursor.lockState = CursorLockMode.Locked;//마우스 커서 고정
Cursor.visible = false;//마우스 커서 보이기
cs


블로그 이미지

stuban

ㅇ.ㅇ

,

Rigidbody.velocity는 월드 좌표로만 수정가능한데.

만약 상대적인 방향으로 움직이려면


velocity를 로컬좌표로 변환하고 수정한후 월드좌표로 다시 바꿔서 넣으면 된다.



1
2
3
4
Vector3 locVel = transform.InverseTransformDirection(rig.velocity);
locVel.x = x;
locVel.z = z;
rig.velocity = transform.TransformDirection(locVel);
cs



출처 : http://answers.unity3d.com/questions/193398/velocity-relative-to-local.html

블로그 이미지

stuban

ㅇ.ㅇ

,

친구가 만들었다고 하길래 나도 만들어본 사운드 매니저.


효과음이나 배경음악을 파일이름으로 재생할 수 있다.

심지어 배경음악 바꿀때 천천히 바꿀 수 도 있음 ㅎ


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class SoundManager : MonoBehaviour {
 
    //싱글톤
    private static SoundManager instance;
    public static SoundManager GetInstance()
    {
        if (!instance)
        {
            instance = GameObject.FindObjectOfType(typeof(SoundManager)) as SoundManager;
            if (!instance)
                Debug.Log("오류");
        }
 
        return instance;
    }
 
 
    public int audioSourceCount = 3;//최대 오디오 소스 개수
 
    [SerializeField]
    [Header("clips"), Tooltip("오디오 클립들")]
    public AudioClip[] BGMs = new AudioClip[2];
    public AudioClip[] SFXs = new AudioClip[3];
 
 
    private AudioSource BGMsource;
    private AudioSource[] SFXsource;
 
    private void OnEnable ()
    {
        BGMsource = gameObject.AddComponent<AudioSource>();
        BGMsource.playOnAwake = false;
        BGMsource.loop = true;
 
        //sfx 소스 초기화
        SFXsource = new AudioSource[audioSourceCount];
 
        for(int i=0;i< SFXsource.Length; i++)
        {
            SFXsource[i] = gameObject.AddComponent<AudioSource>();
            SFXsource[i].playOnAwake = false;
        }
    }
    
    /**********SFX***********/
 
    public void PlaySFX(string name)//효과음 재생
    {
        for(int i=0;i<SFXs.Length;i++)
        {
            if(SFXs[i].name == name)
            {
                GetEmptySource().clip = SFXs[i];
                GetEmptySource().Play();
                return;
            }
        }
    }
 
    private AudioSource GetEmptySource()//비어있는 오디오 소스 반환
    {
        int lageindex = 0;
        float lageProgress = 0;
        for (int i = 0; i < SFXsource.Length; i++)
        {
            if (!SFXsource[i].isPlaying)
            {
                return SFXsource[i];
            }
 
            //만약 비어있는 오디오 소스를 못찿으면 가장 진행도가 높은 오디오 소스 반환
 
            float progress = SFXsource[i].time / SFXsource[i].clip.length;
            if(progress > lageProgress)
            {
                lageindex = i;
                lageProgress = progress;
            }
        }
        return SFXsource[lageindex];
    }
 
    /**********BGM***********/
 
    private AudioClip changeClip;//바뀌는 클립
    private bool isChanging =false;
    private float startTime;
 
 
    [SerializeField]
    [Header("Changing speed"), Tooltip("브금 바꾸는 속도")]
    public float ChangingSpeed;
 
    public void ChangeBGM(string name, bool isSmooth)//브금 변경 (브금이름 , 부드럽게 바꾸기)
    {
        changeClip = null;
        for (int i = 0; i < BGMs.Length; i++)//브금 클립 탐색
        {
            if (BGMs[i].name == name)
            {
                changeClip = BGMs[i];
            }
        }
 
        if (changeClip == null)//없으면 탈주
            return;
 
        if (isSmooth)//스무스 하게 체인지 ~
        {
            startTime = Time.time;
            isChanging = true;
        }
        else
        {
            BGMsource.clip = changeClip;
            BGMsource.Play();
        }
    }
 
    private void Update()
    {
        if (!isChanging) return;
 
        float progress = (Time.time - startTime) * ChangingSpeed;//부드러운 오디오 전환
        BGMsource.volume = Mathf.Lerp(10, progress);
 
        if(progress > 1)
        {
            isChanging = false;
            BGMsource.clip = changeClip;
            BGMsource.Play();
 
            Debug.Log("BGM CHANGE DONE!");
        }
    }
 
}
cs



사실 브금 부분은 아직 제대로 테스트 안해봤음


+ 이 소스 쓰지 마세요 ㅎㅎ

실제로 써보니깐 여러가지 문제가 있었습니다.

문제점들 수정하면 쓸만한데

쓸만하게 만들 자신 있으면 차라리 자기거 만드는게 이득입니다 ㅎ

블로그 이미지

stuban

ㅇ.ㅇ

,

최근 유니티로 안드로이드 빌드를 하려면 이런 오류메시지가 뜬다


내 빈약한 영어 실력으로 대충 해석해 보자면 안드로이드 sdk경로가 맞지않다는 뜻인데.


분명히 모든 경로가 완벽한걸 확인해도 저 메시지는 계속 뜨게 된다.

물론 디버그 창에도 오류가 뜨게 된다


(디버그 창에 나오는 오류메시지)

Error building Player: CommandInvokationFailure: Unable to list target platforms. Please make sure the android sdk path is correct. See the Console for more details. 


저 위의 메시지로 구글링을 해본결과


sdk를 다운받을 수 있는 안드로이드 스튜디오가 업뎃 되면서

유니티가 쓰던 기능이 바뀌었다고 한다....


해결 방법은 아래 링크에서 안드로이드 스튜디오를 다운그레이드 하고 sdk를 다시 다운 받는 방법이 있으나...

https://developer.android.com/studio/archive.html


다행히도 저 해결법을 알려준 글에서 친절하게도 예전버전의 바뀐 부분만 올려 주셨다!

http://dl-ssl.google.com/android/repository/tools_r25.2.5-windows.zip


sdk의 tools폴더를 지우거나 이름을 바꿔놓고 다운받은 파일을 tools 로바꾸면 정상적으로 빌드 할 수 있게 된다.


출처 : http://www.devkorea.co.kr/bbs/board.php?bo_table=m03_qna&wr_id=79671


네이버 원글 : http://stuban.blog.me/220995514977

블로그 이미지

stuban

ㅇ.ㅇ

,