팀 프로젝트에서 심전도 그래프 그리는 기술이 필요하다.
파이썬으로도 실시간 그래프를 그릴 수 있지만, 메타버스 환경 화면에서 그래프 화면을 바로 띄우고 싶어 유니티로 구현을 시도해봤다.
1. 라즈베리파이에서 실시간으로 txt파일에 심전도 데이터를 기록
2. 그 txt파일을 실시간으로 pc(또는 서버)에 전송
3. pc 또는 서버에 있는 심전도 txt파일을 유니티에서 읽어, 실시간으로 그래프 그림 <<3번 과정의 내용이다.
3-1. https://dhshin94.tistory.com/m/160
참고해서 그래프 기본 틀 만들기
3-2. https://coderzero.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%86%8C%EC%8A%A4-%ED%85%8D%EC%8A%A4%ED%8A%B8txt-%ED%8C%8C%EC%9D%BC-%EC%9D%BD%EA%B3%A0-%EC%93%B0%EA%B8%B0
참고해서 그래프 기본 틀 만들기
3-2. https://coderzero.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%86%8C%EC%8A%A4-%ED%85%8D%EC%8A%A4%ED%8A%B8txt-%ED%8C%8C%EC%9D%BC-%EC%9D%BD%EA%B3%A0-%EC%93%B0%EA%B8%B0
참고해서 txt 파일에서 값을 불러와 점 찍기
3-3. 점이 그래프 가로 길이 넘어서까지 추가되면 초기화한 뒤 다시 그리는 기능 추가
3-3. 점이 그래프 가로 길이 넘어서까지 추가되면 초기화한 뒤 다시 그리는 기능 추가
이렇게 구상하고 들어갔는데, 실제로 코드 짜다보니 바뀐 게 좀 있다. 챗지피티 도움도 많이 받았다...
기본 세팅
using UnityEngine;
using UnityEngine.UI;
using System;
public class GraphMakerChatGPT : MonoBehaviour
{
public GameObject DotPrefab; // 그래프 점 프리팹
public Transform DotGroup; // 생성한 그래프 점을 자식으로 가질 부모 오브젝트
public RectTransform GraphArea; // 그래프 영역의RectTransform
private float graph_Width;
private float graph_Height; // 그래프 영역의 길이, 높이 저장할 변수
private const int ArraySize = 100; // 가로 점 갯수
private int[] HeartBeatValue = new int[ArraySize]; // 심전도값 저장할 배열 ArraySize개 만들기 > 값 0으로 통일
private GameObject[] dots = new GameObject[ArraySize]; // 생성된 점들을 저장할 배열
private int currentIndex = 0;
private float timePassed = 0f; // 경과한 시간을 추적
private const float updateTime = 0.1f; // 그래프를 업데이트할 시간 간격(0.1초)
//const : 1. 반드시 선언과 동시에 값 초기화 2. 한번 값이 할당되면 이후 변경 불가능 3.자동으로 static
private const int MaxValue = 1000; //그래프 최댓값
void Start() //시작할때 실행하는 함수
{
graph_Width = GraphArea.rect.width;
graph_Height = GraphArea.rect.height;
}
void Update() //프레임마다 실행하는 함수
{
timePassed += Time.deltaTime; // Unity 엔진에서 프레임 간 경과 시간을 나타내는 변수
// 각 프레임 사이의 시간 간격
if (timePassed >= updateTime)
{
timePassed = 0f;
var rand = new System.Random();
int HeartBeat = rand.Next(0, MaxValue); // 심전도 값 랜덤 부여 (본편때는 텍스트에서 불러온값으로 변경하기)
HeartBeatValue[currentIndex] = HeartBeat;
DrawGraph(HeartBeatValue[currentIndex], currentIndex);
if (currentIndex + 1 == ArraySize){ // 가로 다채우면 모든 값 0으로 바꾸기
for (int i = 0; i < ArraySize; i++) HeartBeatValue[i] = MaxValue / 2;
for (int i = 0; i < ArraySize; i++) DrawGraph(HeartBeatValue[i], i);
}
currentIndex = (currentIndex + 1) % ArraySize; // 다음 인덱스로 이동
}
}
private void DrawGraph(int value, int index)
{
float startPosition = -graph_Width / 2; // 그래프 영역의 길이 / 2 에 -를 붙이면 시작위치
float maxYPosition = graph_Height * 2/3; // 그래프 영역의 높이 * 2/3 => 점을 찍을 최대 높이
if (dots[index] == null){ // 이전에 생성된 점이 없는 경우 점 오브젝트 생성 및 부모 설정
dots[index] = Instantiate(DotPrefab, DotGroup, true);
}
//각 컴포넌트 가져오기
RectTransform dotRT = dots[index].GetComponent<RectTransform>();
Image dotImage = dots[index].GetComponent<Image>();
float yPosOffset = value / (float)MaxValue; // 그래프의 최댓값으로 나눠, 값을 0과 1 사이로 정규화
dotRT.anchoredPosition = new Vector2(startPosition + (graph_Width / (ArraySize - 1) * index), maxYPosition * yPosOffset - graph_Height/3);
}
}
C#과 유니티가 이번이 처음이라 많이 헤맸다.
'code > Unity' 카테고리의 다른 글
[유니티] 심전도 그래프 그리기 - 3. txt 파일에서 값 읽어와 그래프 그리기 (0) | 2024.03.24 |
---|---|
[유니티] 심전도 그래프 그리기 - 2. 선 그리기 (0) | 2024.03.24 |