
#20221201 :: 라인렌더러 동기화(Awake(Pre Start), Start, Update(Post Start)
#20221202 :: 라인렌더러 꾸미기, 베지어 곡선, 애트리뷰트
#20221204 :: 아이디어 조금
#20221205 :: 터미널 개편
#20221201 :: 라인렌더러 동기화(Awake(Pre Start), Start, Update(Post Start)
라인렌더러를 동기화하기에 앞서 하나 확실하게 해야 할 점.
BackGround의 Position 업데이트 ⇒ Awake
나머지 노드들의 Position 업데이트 ⇒ Start
로 설정해야만 한다.
그도 그럴게 부모인 BackGround의 Position에 따라 나머지 자식 노드들이 영향받기 때문이다.
만약 반대로 자식 노드의 Position 업데이트가 먼저 일어나면 이후 일어나는 BackGround의 Position 업데이트에 의해
이상한 좌표를 가르키게 된다. (Pos + Bag.Pos)
라인렌더러 동기화
- 기본 업데이트
- 씬 이동 업데이트
기본작업
<*TerminalData Class*>
public Dictionary<string, int> linkNode{get; private set;}
linkNode는 List에서 Dictionary로 수정.
이제는 Key로 linkNumber를, Value로는 nodeIndex를 받는다.
linkNumber는 동기화를 위해 필요한 고유 넘버인데
만약 Input 이라면 I 로 시작하고 ex) I1, I2, …
Output 이라면 O 로 시작하게된다. ex) O1, O2, …
input 과 output 에 linkNumber를 설정해야하는 것을 꼭 명심!!!!@@@!!!
<*NodeOutput Class*>
TerminalManager.Instance.terminalStatus[origin.world][origin.nodeIndex]
.Link(linkNumber, input.origin.nodeIndex);
TerminalManager.Instance.terminalStatus[origin.world][input.origin.nodeIndex]
.Link(input.linkNumber, origin.nodeIndex);
마찬가지로 Link의 매개변수에는 현재(this)의 linkNumber와 그에 맞는 nodeIndex가 들어간다.
헷갈린다면
TerminalManager.Instance.terminalStatus[나][나].Link(나, input);
TerminalManager.Instance.terminalStatus[input][input].Link(input, 나);
로 기억하자. 나에 대응되는 것과 input에 대응되는 것으로 구별하면 된다.
업데이트
if (input != null && TerminalManager.Instance.currentNode != this
&& TerminalManager.Instance.currentNode != input)
{
start = this.transform.position;
target = input.transform.position;
lineRenderer.SetPosition(0, start);
lineRenderer.SetPosition(1, target);
}
만약 input 이 존재하고, output과 input 그 누구것도 클릭하지 않았다면
즉, 다른 노드를 클릭했거나, 그 노드를 이동중이라면 라인렌더러는 그 이동에 맞게 따라간다. (즉 동기화된다.)
이를 구현하기 위해서 다른 스크립트에 적용할 규칙이 있는데
바로, 노드를 드래그해서 이동하는 중이라면 TerminalManager.Instance.currentNode를 바꿔줘야 한다는 점이다.
일단 지금은 임의적으로 이동중에는 null 을 받도록 하고 있다.
나중에 새로 추가하는 노드들의 경우에도 잊지않고 처리할수 있도록 하자.
씬 이동 동기화(업데이트)
오브젝트간의 SetActive가 언제 일어나는지에는 차이가 있다.
그래서 Output이 Input을 찾는 코드를 Start에 넣으면 Input이 SetActive되기전에 Output에서 먼저 그 코드가 실행되서
결국엔 찾지 못하더라.
이를 해결하기위한 방법으로는
- 코루틴 : .5초 안에 아마 생성되겠지라고 믿기.
하지만 이는 컴퓨터 성능에 따라서 결과가 달라진다. 그래서 이렇게 하면 절대 안될 것 같다.
(플레이어 턴제도 코루틴으로 했다가 버그가 발생해서 지금은 적의 이동이 끝날때까지 기다린뒤에 턴이 바뀌는걸로 처리하고 있다.)
⇒ 폐기 - while 로 hit가 true 될때까지 루프 돌리기
방금했는데 유니티 멈춤..
레이캐스트를 매 프레임보다 더 빠른 개념인 루프에서 돌렸으니 아마 컴퓨터 많이 혹사시켰을거다..
⇒ 폐기 - 업데이트에서 부분적으로 start처럼 사용
순서상 Awake → Start → Update 이므로 아마 되지않을까 했는데 정말로 되더라
⇒ 채용. 근데 일종의 편법이라서 뭔가 다른방법이 있을수도
일명 AnotherStart(Start2)
if(!anotherStart){
foreach (var i in TerminalManager.Instance.terminalStatus[origin.world][origin.nodeIndex].linkNode)
{
if (i.Key == this.linkNumber)
{
Debug.Log("들어왔냐?");
int inputIndex = i.Value;
Vector3 inputPos = TerminalManager.Instance.terminalStatus[origin.world][inputIndex].nodePos
+ (origin.transform.position - this.transform.position) + new Vector3(0.1f, 0f, 0f);
Debug.Log(inputPos);
Debug.DrawRay(inputPos, Vector3.back, Color.red, 100f);
RaycastHit2D hit = Physics2D.Raycast(inputPos, Vector3.back);
if (hit == true && hit.collider.name == "Input")
{ // input과 충돌에 성공하면 연결하기
Debug.Log("닿았지롱");
target = hit.collider.transform.position;
input = hit.transform.GetComponent<NodeInput>(); // 이 if 문에 들어오는 순간 이 문구가 실패할 일은 없음.
input.output = this; // 여기서 input의 output도 설정하므로 InputNode 스크립트에서는 별다른 수정사항이 필요없음.
anotherStart = true;
}
break;
}
}
}
코드블럭 안에서 anotherStart를 true로 만들어주기때문에 위의 코드는 씬 시작시 한번밖에 일어나지 않는다.
모든 Update는 모든 Start보다 나중에 일어난다는 개념에서 응용!
#20221202 :: 라인렌더러 꾸미기, 베지어 곡선, 애트리뷰트
라인 렌더러 꾸미기
Can't set color for LineRenderer, always comes out as magenta or black
I am trying to create a line renderer and set its color in a C# script. By default line renderers are always magenta. I found three different ways in...
forum.unity.com
머터리얼을 먼저 지정하라더라 어쩐지 색깔 안바뀌더라
베지어 곡선
베지어 곡선 구현
베지어 곡선은 시작점과 끝점을 가지고, 그 위에 여러 개의 조절점으로 이루어진 곡선이다.인자 : 조절점들...
blog.naver.com
구현
/** 베지어 곡선 **/
///////////////////////////////////////////////////
public void BezierLine(){
if(start == target){
this.lineRenderer.positionCount = 2;
this.lineRenderer.SetPosition(0, start);
this.lineRenderer.SetPosition(1, target);
}else{
Vector3[] points = new Vector3[this.pointCount];
Vector3 p1 = this.start;
Vector3 p2 = this.start + new Vector3(1f, -1f, 0f);
Vector3 p3 = this.target + new Vector3(-1f, 1f, 0f);
Vector3 p4 = this.target;
for (int i = 0; i < this.pointCount; i++)
{
points[i] = this.GetBezierPosition(p1, p2, p3, p4, (float)i / (this.pointCount - 1));
}
this.lineRenderer.positionCount = this.pointCount;
this.lineRenderer.SetPositions(points);
}
}
public Vector3 GetBezierPosition(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, float t){
Vector3 q1 = Vector3.Lerp(p1, p2, t);
Vector3 q2 = Vector3.Lerp(p2, p3, t);
Vector3 q3 = Vector3.Lerp(p3, p4, t);
Vector3 r1 = Vector3.Lerp(q1, q2, t);
Vector3 r2 = Vector3.Lerp(q2, q3, t);
return Vector3.Lerp(r1, r2, t);
}
///////////////////////////////////////////////////
이제는 Start와 Target을 직접 SetPosition 하지 않고 베지어곡선에서 한꺼번에 구현.
단 start와 target이 같을경우엔(라인이 없을 때) 기존의 방식대로 SetPosition.
p2랑 p3는 조금 더 조절해 봐야할듯?
결과
애트리뷰트
[Unity] Attribute 애트리뷰트
Attribute(속성) 는 class 의 위에 표시 되어, 스크립트 프로퍼티나 함수에 특별한 동작을 나타냅니다. 유니티 - Attribute(속성) 문서 1. 인스펙터 노출 관련 Attribute [SerializeField] 데이터를 직렬화 해주는
zagara.tistory.com
#20221204 :: 아이디어 조금
아이디어 :
월드 하나, 터미널 하나에 스테이지랑 노드를 전부 때려박는건? 어떨까
(월드 셀렉트가 별도로 존재하지 않음.)
→ 스테이지를 클리어하면 보스 캐릭터 출몰
→ 요리를 노드로 이어서 만족을 시키면 다음스테이지 해금, 연결
→ 노드를 이동 못하게 막는 방어벽
퍼즐 아이디어 :
조합 노드 에 스테이지 두개를 연결하면 맵 두개가 조합된(합쳐진) 스테이지가 나온다.
고양이는 6명의 요리고수들에게서 요리를 배워
요즘 무기력한 주인에게 음식을 대접하고자 한다.
#20221205 :: 터미널 개편
터미널 대대적인 개편
- 월드 개념 삭제
- 1씬 1터미널 (모든 레벨의 노드를 한씬에서 관리)
- 노드 그래픽 수정
- 레벨 설명 패널 수정(근데 코드 더러워서 개편 필요)
'개인 프로젝트 > Node Princess' 카테고리의 다른 글
Node Princess :: 개발일지 #7 - A* 패스파인딩 (0) | 2024.02.16 |
---|---|
Node Princess :: 개발일지 #6 - 캐릭터 컨셉 (0) | 2024.02.16 |
Node Princess :: 개발일지 #4 - 터미널 구현 (1) (1) | 2024.02.15 |
Node Princess :: 개발일지 #3 - 터미널(월드 선택) 컨셉 (0) | 2024.02.15 |
Node Princess :: 개발일지 #2 - 타이틀 만들기 (1) | 2024.02.15 |
틀린 부분은 언제든지 말씀해주세요!!! 감사합니다!