'Unity'에 해당되는 글 184건
- 2020.12.30 유니티 그림자
- 2020.12.30 유니티 에러코드 애니메이터
- 2020.12.24 MapBorder
- 2020.12.23 리플렉션
- 2020.12.02 포톤 설치
- 2020.11.24 유니티 단축키
- 2020.11.16 Resource ID out of range in GetResource
- 2020.11.11 Streaming of 'mpeg' on this platform is not supported
레이어가 두개면 각각 개별로 돌아가면서 혼합된다
기본값은 웨이트가 0이라서 혼합이 안된다 1로 변경하자
에러코드 100일때 뜨는 팝업
반드시 화살표 순서대로 한다. 순서가 어긋나면 값이 초기화된다
사진에서는 파라미터 앞글자가 대문자인데 가급적 소문자로 해주자
빠져나올땐 낫 이퀄로 한다
public LoaderState state = LoaderState.None;
public ErrorCode errorCode = ErrorCode.None;
public enum LoaderState
{
None,
Connect,
Download,
Error,
Exit
}
public enum ErrorCode
{
None,
InternetConnection = 100,
RunExistingFile = 200,
NoFile = 300
}
void Update()
{
animatorState.SetInteger(nameof(errorCode), (int)errorCode);
animatorState.SetInteger(nameof(state), (int)state);
}
파라미터를 연동시켜준다 끝
'Unity' 카테고리의 다른 글
유니티 그림자 (0) | 2020.12.30 |
---|---|
유니티 단축키 (0) | 2020.11.24 |
Resource ID out of range in GetResource (0) | 2020.11.16 |
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MapBorder : MonoBehaviour {
private void OnDrawGizmos()
{
Gizmos.DrawWireCube(borderCenter, borderSize);
}
public enum DropOption
{
None
, Respawn
, Destroy
}
public DropOption dropOption = DropOption.Respawn;
public Vector3 borderCenter = Vector3.zero;
public Vector3 borderSize = new Vector3(200,100,200);
public Transform respawnPoint;
Vector3 firstPosition;
Quaternion firstRotation;
// Use this for initialization
void Start ()
{
firstPosition = transform.position;
firstRotation = transform.rotation;
}
// Update is called once per frame
void Update () {
var pos = transform.position;
pos.x = Mathf.Clamp(pos.x, borderCenter.x - borderSize.x, borderCenter.x + borderSize.x );
pos.y = Mathf.Min(pos.y, borderCenter.y + borderSize.y );
pos.z = Mathf.Clamp(pos.z, borderCenter.z - borderSize.z , borderCenter.z + borderSize.z);
transform.position = pos;
if (transform.position.y<borderCenter.y- borderSize.y )
{
switch (dropOption)
{
case DropOption.None:
break;
case DropOption.Respawn:
if (respawnPoint == null)
{
transform.position = firstPosition;
transform.rotation = firstRotation;
}
else
{
transform.position = respawnPoint.transform.position;
transform.rotation = respawnPoint.transform.rotation;
}
break;
case DropOption.Destroy:
Destroy(gameObject);
break;
default:
break;
}
}
}
}
현재 클래스 명
public class ParentClass
{
public class TestClass
{
public void Log()
{
var className = GetType().Name
Debug.Log(className); //TestClass가 나옴
}
}
}
현재 클래스 명 (부모포함)
var className = typeof(TestClass).FullName
Debug.Log(className); //ParentClass+TestClass가 나옴
해당 클래스가 존재하는지
public static bool CheckClassExists(string className)
{
return System.Type.GetType(className) != null;
}
현재 함수 명
var methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
Debug.Log(methodName);
필드명들
string[] GetClassFieldNames<T>(T targetClass)
{
var fields = typeof(T).GetFields();
return System.Array.ConvertAll(fields, x => x.Name);
}
필드명들2
string[] GetClassFieldNames<T>(T targetClass)
{
var fields = typeof(T).GetFields();
return Array.ConvertAll(fields, x => $"{x.Name} - type: {x.FieldType}");
}
특정클래스의 필드명과 함수명에 접근
var methods = typeof(Class).GetMethods();
foreach (var method in methods)
{
EditorGUILayout.LabelField(method.Name);
}
var fields = typeof(Class).GetFields();
foreach (var field in fields)
{
EditorGUILayout.LabelField(field.Name);
}
클래스할당과 연동
구조체에는 씨알도 안 먹히니 헛고생 하지 말자
public class SampleClass
{
string numStr = "0.5";
int num = 1;
float value = 1.5f;
public SampleClass() { }
public SampleClass (string stringData)
{
var fields = typeof(SampleClass).GetFields();
var targetClass = this;
for (int i = 0; i < fields.Length; i++)
{
if (fields[i].FieldType == typeof(string))
{
fields[i].SetValue(targetClass, stringData);
}
else if (fields[i].FieldType == typeof(bool))
{
fields[i].SetValue(targetClass, bool.Parse(stringData));
}
else if (fields[i].FieldType == typeof(char))
{
fields[i].SetValue(targetClass, char.Parse(stringData));
}
else if (fields[i].FieldType == typeof(int))
{
fields[i].SetValue(targetClass, int.Parse(stringData));
}
else if (fields[i].FieldType == typeof(uint))
{
fields[i].SetValue(targetClass, uint.Parse(stringData));
}
else if (fields[i].FieldType == typeof(long))
{
fields[i].SetValue(targetClass, long.Parse(stringData));
}
else if (fields[i].FieldType == typeof(ulong))
{
fields[i].SetValue(targetClass, ulong.Parse(stringData));
}
else if (fields[i].FieldType == typeof(float))
{
fields[i].SetValue(targetClass, float.Parse(stringData));
}
else if (fields[i].FieldType == typeof(double))
{
fields[i].SetValue(targetClass, double.Parse(stringData));
}
else
{
fields[i].SetValue(targetClass, stringData);
}
}
}
public override string ToString()
{
var fields = GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
return string.Join("\n",System.Array.ConvertAll(fields, x => $"{x.Name}: {x.GetValue(x)}" ));
}
/*
public override string ToString()
{
var fields = typeof(SampleClass).GetFields();
string returnString = "";
for (int i = 0; i < fields.Length; i++)
{
if (i>0)
{
returnString += "\n";
}
returnString += $"{fields[i].Name}:{fields[i].GetValue(this)}";
}
return returnString;
}
*/
public static implicit operator string(SampleClass _this) //암시적 형변환, 명시적은 explicit
{
return _this.ToString();
}
}
public class MainClass : MonoBehaviour
{
void Start()
{
Debug.Log("new SampleClass()\n" + new SampleClass());
Debug.Log("new SampleClass(\"123\")\n" + new SampleClass("123"));
}
}
생성자 자동 할당
public class SampleClass
{
public int number;
public string name;
public SampleClass()//생성자(자동)
{
var targetClass = new SampleClass(123, "Name");
//this.number = targetClass.number;
//this.name = targetClass.name;
//이렇게 안쳐도 됨
var fields = GetType().GetFields();
foreach (var field in fields)
{
field.SetValue(this, field.GetValue(targetClass));
}
}
public SampleClass(int number, string name)//생성자
{
this.number = number;
this.name = name;
}
}
클래스 깊은복사, 간단한 형식만 된다. 다중 클래스등은 불가 (문자열도 안되는듯?)
public class SampleClass
{
public int number;
public string name;
public SampleClass Clone()
{
var targetClass = new SampleClass();
var fields = GetType().GetFields();
foreach (var field in fields)
{
field.SetValue(this, field.GetValue(targetClass));
}
return targetClass;
}
}
위에거의 외부버전
https://gist.github.com/ahzkwid/69d7703736b5bca29b0131270ee9164a
static void CopyClass<T>(T source, T target)
{
var fields = target.GetType().GetFields();
foreach (var field in fields)
{
field.SetValue(target, field.GetValue(source));
}
}
BindingFlags 옵션들 (지정 안되면 논퍼블릭까지 전부 반환함)
System.Reflection.BindingFlags.NonPublic //퍼블릭이 아닌것들
System.Reflection.BindingFlags.Public //퍼블릭인것들
System.Reflection.BindingFlags.Instance //일반적인 변수들 (지역변수)
System.Reflection.BindingFlags.Static //전역변수들
//예시 (일반적인 필드값 불러오기)
var fields = GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
Type검사
field.FieldType.IsValueType //bool,int,float
field.FieldType.IsArray //bool[], int[], float[]
field.FieldType.IsClass //bool[], int[], float[], string, SubClass
field.FieldType.IsEnum //Enum타입
field.FieldType.Equals(typeof(string)) //string
//클래스인지 검사
var fieldType = field.FieldType;
if (fieldType.IsClass&&(fieldType.IsArray==false)&&(fieldType.Equals(typeof(string)) == false))
{
//Sub클래스일경우에만
}
//List인지 검사
if((fieldType.IsGenericType) && fieldType.GetGenericTypeDefinition() == typeof(List<>))
오브젝트에서 ?배열을 반환
이런 X같은 코드도 쓸데가 있다
object objData;
var arrDatas = (System.Collections.IList)objData;
Debug.Log($"arrDatas[0]: {arrDatas[0]}");
Debug.Log($"arrDatas[1]: {arrDatas[1]}");
Debug.Log($"arrDatas.Count: {arrDatas.Count}");
오브젝트 리스트나 오브젝트 배열을 특정 형배열로 변환
using System.Linq;
//오브젝트 리스트를 float 배열로 변환
var objList=new List<object>();
float[] floatArray=objList.Cast<float>().ToArray();
//오브젝트 배열을 string 배열로 변환
object[] objArray = new object[1];
string[] stringArray = objArray.Cast<string>().ToArray();
문자열을 FieldType으로 변환
var text = "105.0";
var converter = TypeDescriptor.GetConverter(field.FieldType);
var data = converter.ConvertFrom(text);
field.SetValue(tempClass, data);
배열에 할당된 변수명 추출
v1
string[] ArrayToFieldNames(object containingClassWithArray, object[] array)
{
var fields = containingClassWithArray.GetType().GetFields();
var fieldNames = System.Array.ConvertAll(array, x => fields.First(field => field.GetValue(containingClassWithArray) == x).Name);
return fieldNames;
}
/*
예시
public class Coordinator : MonoBehaviour
{
public BodyPart head;
public BodyPart top;
public BodyPart bottom;
public BodyPart gloves;
public BodyPart shoes;
public BodyPart hair;
public BodyPart eye;
public BodyPart skin;
public BodyPart[] bodyParts
{
get
{
return new BodyPart[] { head, top, bottom, gloves, shoes, hair, eye, skin };
}
}
}
이렇게 있을때
var bodyPartNames = ArrayToFieldNames(coordinator, coordinator.bodyParts);
Debug.Log(string.Join(",",bodyPartNames));
하면 head,top,bottom,gloves,shoes,hair,eye,skin로 나온다
*/
v2
v1과 구조상으로는 동일한데 클래스내부로 넣어버렸다.
이게 더 편함
string[] ArrayToFieldNames(object[] array)
{
var fields = GetType().GetFields();
var fieldNames = System.Array.ConvertAll(array, x => fields.First(field => field.GetValue(this) == x).Name);
return fieldNames;
}
/*
//샘플
public BodyPart head;
public BodyPart top;
public BodyPart bottom;
public BodyPart gloves;
public BodyPart shoes;
public BodyPart hair;
public BodyPart eye;
public BodyPart skin;
public BodyPart[] bodyParts
{
get
{
return new BodyPart[] { head, top, bottom, gloves, shoes, hair, eye, skin };
}
}
public string[] bodyPartNames
{
get
{
return ArrayToFieldNames(bodyParts);
}
}
*/
근데 이방법 쓸바엔 그냥 클래스 안에 name값 넣어서 써라
var value = field.GetValue(component);
if (value==null)
{
continue;
}
https://x.com/ahzkwid/status/1799549808312746276
field.GetValue(component)을 ==null체크시 정상동작하지 않는 현상이 있는데
var value = field.GetValue(component);
if (value==null)
{
continue;
}
if (value.Equals(null))
{
continue;
}
이렇게 하면 된다
'Unity > C#' 카테고리의 다른 글
MapBorder (0) | 2020.12.24 |
---|---|
그래디언트효과 (0) | 2020.10.20 |
유니티 에디터 관련 (0) | 2020.10.05 |
가입하고
dashboard.photonengine.com/ko-KR/
여기에 들어가서
Photon PUN은 VRChat같은거 만들때 씀, 전부 간접통신임
Photon BOLT는 오버워치 같은거 만들때 쓰고 직접통신, NAT나 방화벽등으로 인해 직접연결이 불가한경우 릴레이를 통한 간접연결이 됨, 방장이 나가면 방이 닫힌다
설정한다
어플리케이션 ID 필요함
유니티로 가서
PUN1
assetstore.unity.com/packages/tools/network/photon-unity-networking-classic-free-1786
다운로드해
펀 ID를 넣자
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhotonInit : Photon.PunBehaviour
{
public string serverName = "Default0001";
public int roomNumber = 0;
public Transform spawnPoint;
public GameObject playerPrefab;
// Start is called before the first frame update
void Start()
{
PhotonNetwork.ConnectUsingSettings(serverName);
PhotonNetwork.ConnectToBestCloudServer(serverName);
}
/// <summary>
/// 로비에 들어가기 성공했을때
/// </summary>
public override void OnConnectedToPhoton()
{
Debug.Log("ConnectedToPhoton");
}
/// <summary>
/// 로비에 들어가기 성공했을때
/// </summary>
public override void OnJoinedLobby()
{
Debug.Log("JoinedLobby");
PhotonNetwork.JoinRandomRoom();
}
/// <summary>
/// PhotonNetwork.autoJoinLobby 이 false 인 경우에만 마스터 서버에 연결되고 인증 후에 호출
/// </summary>
public override void OnConnectedToMaster()
{
Debug.Log("ConnectedToMaster");
PhotonNetwork.JoinLobby(); //로비접속
}
/// <summary>
/// 룸입장실패
/// </summary>
/// <param name="codeAndMsg"></param>
public override void OnPhotonRandomJoinFailed(object[] codeAndMsg)
{
Debug.LogError("PhotonRandomJoinFailed");
PhotonNetwork.CreateRoom(roomNumber.ToString());
}
/// <summary>
/// 룸생성실패
/// </summary>
/// <param name="codeAndMsg"></param>
public override void OnPhotonCreateRoomFailed(object[] codeAndMsg)
{
Debug.LogError("PhotonCreateRoomFailed");
PhotonNetwork.JoinRandomRoom();
}
/// <summary>
/// 룸생성 성공
/// </summary>
public override void OnCreatedRoom()
{
Debug.Log("CreatedRoom");
}
/// <summary>
/// 룸접속 성공
/// </summary>
public override void OnJoinedRoom()
{
Debug.Log("JoinedRoom");
CreatePlayer();
}
void CreatePlayer()
{
var pos = Vector3.zero;
var rot = Quaternion.identity;
if (spawnPoint != null)
{
pos = spawnPoint.position;
rot = spawnPoint.rotation;
}
string objName = "Player";//플레이어 프리팹이 없으면 기본 플레이어가 호출됨
if (playerPrefab != null)
{
objName = playerPrefab.name; //프리팹 이름은 Player로 하면 안됨
}
PhotonNetwork.Instantiate(objName, pos, rot);
}
// Update is called once per frame
void Update()
{
}
}
PUN2
https://assetstore.unity.com/packages/tools/network/pun-2-free-119922
다운로드해
펀 ID를 넣자
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhotonInit : MonoBehaviourPunCallbacks
{
public string serverName = "Default0001";
public int roomNumber = 0;
public Transform spawnPoint;
public GameObject playerPrefab;
// Start is called before the first frame update
void Start()
{
PhotonNetwork.ConnectUsingSettings();
PhotonNetwork.ConnectToBestCloudServer();
}
/// <summary>
/// 로비에 들어가기 성공했을때
/// </summary>
public override void OnJoinedLobby()
{
Debug.Log("JoinedLobby");
//PhotonNetwork.JoinRandomRoom(); //로비사용시
}
/// <summary>
/// PhotonNetwork.autoJoinLobby 이 false 인 경우에만 마스터 서버에 연결되고 인증 후에 호출
/// </summary>
public override void OnConnectedToMaster()
{
Debug.Log("ConnectedToMaster");
PhotonNetwork.JoinRandomRoom();
//PhotonNetwork.JoinLobby(); //로비접속 (로비사용시)
}
/// <summary>
/// 룸입장실패
/// </summary>
/// <param name="codeAndMsg"></param>
public override void OnJoinRandomFailed(short returnCode, string message)
{
Debug.LogError("PhotonRandomJoinFailed");
PhotonNetwork.CreateRoom(roomNumber.ToString());
}
/// <summary>
/// 룸생성실패
/// </summary>
/// <param name="codeAndMsg"></param>
public override void OnCreateRoomFailed(short returnCode, string message)
{
Debug.LogError("PhotonCreateRoomFailed");
PhotonNetwork.JoinRandomRoom();
}
/// <summary>
/// 룸생성 성공
/// </summary>
public override void OnCreatedRoom()
{
Debug.Log("CreatedRoom");
}
/// <summary>
/// 룸접속 성공
/// </summary>
public override void OnJoinedRoom()
{
Debug.Log("JoinedRoom");
CreatePlayer();
}
void CreatePlayer()
{
var pos = Vector3.zero;
var rot = Quaternion.identity;
if (spawnPoint != null)
{
pos = spawnPoint.position;
rot = spawnPoint.rotation;
}
string objName = "My Robot Kyle -done-";//플레이어 프리팹이 없으면 기본 플레이어가 호출됨
if (playerPrefab != null)
{
objName = playerPrefab.name; //프리팹 이름은 Player로 하면 안됨
}
PhotonNetwork.Instantiate(objName, pos, rot, 0);
}
// Update is called once per frame
void Update()
{
}
}
이렇게 만들어서
씬에 넣는다.
PUN2
api는 여기 참조
PUN1
doc-api.photonengine.com/ko-kr/pun/current/class_photon_1_1_pun_behaviour.html
실행하면 이렇게 나온다
PUN1
로그를 보면 이렇게
빨간줄이 있지만 단지 방이 없어서 뜬것이니 쫄지 말자 정상이다
PUN2
로그를 보면 이렇게
빨간줄이 있지만 단지 방이 없어서 뜬것이니 쫄지 말자 정상이다
시작하면 이렇게 나올것이다.
1. 포톤서버에 연결하고
2. 로비에 들어가서
3. 룸에 들어가는것이다
기본적인 네트워킹 시스템은 완성했다
'Unity > Photon' 카테고리의 다른 글
포톤 챗 (0) | 2021.07.07 |
---|---|
포톤 볼트 (0) | 2021.07.06 |
포톤 커스텀 플레이어 만들기 (0) | 2021.07.04 |
Ctrl + Shift + F : 선택한 오브젝트를 현재 씬뷰의 위치로 이동시킴
F : 씬뷰의 위치를 선택한 오브젝트의 위치로 이동시킴
'Unity' 카테고리의 다른 글
유니티 에러코드 애니메이터 (0) | 2020.12.30 |
---|---|
Resource ID out of range in GetResource (0) | 2020.11.16 |
Streaming of 'mpeg' on this platform is not supported (0) | 2020.11.11 |
Texture2D가 매프레임마다 생성됨,
얘는 씬이동이나 오브젝트 삭제시에도 안 지워지므로 반드시 한번만 생성해서 쓰는식으로 해야함
'Unity' 카테고리의 다른 글
유니티 단축키 (0) | 2020.11.24 |
---|---|
Streaming of 'mpeg' on this platform is not supported (0) | 2020.11.11 |
투명 렌더텍스처 (0) | 2020.11.10 |
UnityWebRequestMultimedia.GetAudioClip을 사용시 빌드플랫폼이 윈도우로 설정되어있으면 발생함
안드로이드나 애플로 돌리자
'Unity' 카테고리의 다른 글
Resource ID out of range in GetResource (0) | 2020.11.16 |
---|---|
투명 렌더텍스처 (0) | 2020.11.10 |
유니티 아틀라스 이미지 깨질때 (0) | 2020.11.09 |