이 두 코드 중 어느 것이 더 낫습니까? 지역 변수 또는 클래스 변수를 만드시겠습니까?


11

더 많은 게임을 만들고 더 어리석은 질문을합니다.

잘만되면 이것은 매우 간단하다. 강체에 힘을 가하여 Player 객체를 이동시키는 매우 기본적인 클래스를 만들고 있습니다.하지만 매 프레임마다 Update 내에서 rb 또는 로컬 변수에 대한 클래스 참조를 만들어야합니까? (이것은 Monobehaviour.GameObject unity parent 클래스에 이미 존재한다는 것을 명심하십시오).

많은 지역 변수를 수행하면 루프가 전체적으로 느려질 지 궁금합니다 (지역에 따라 함수 자체 내부를 의미하며 클래스의 상단이 아니라 올바른 용어를 사용하기를 바랍니다).

여기 내가 생각하는 두 가지 방법이 있습니다.

public class Player : MonoBehaviour {

private void FixedUpdate()
{
    Rigidbody rb = GetComponent<Rigidbody>();

    float v = Input.GetAxis("Vertical");

    rb.AddForce(v * rb.transform.forward * Const.walkForce);
}
}

또는...

public class Player : MonoBehaviour {
Rigidbody rb;

private void Awake()
{
    rb = GetComponent<Rigidbody>();
}

private void FixedUpdate()
{
    float v = Input.GetAxis("Vertical");

    rb.AddForce(v * rb.transform.forward * Const.walkForce);
}
}

4
이것은 코드 검토 SE에 대한 질문처럼 보입니다.
Orphevs

1
float va class 속성을 만들 수도 있습니다.
차드

나는 아마도 실제로 Chad를 끝낼 것입니다. 왜냐하면 클래스 내에서 두 가지 방법으로 사용할 것입니다. 많은 코드로 그것을 부 풀리지 않고 로컬 대 클래스 변수에 대한 질문을 얻는 것은 실제로 간단한 코드였습니다. 나는 변수를 로컬로 유지하는 것을 좋아하고 (그리고 어디에서나 '정지'!) 물론, 물론 각각에 대해 하나의 클래스 변수를 갖는 대신 물건을 복제하지 않도록해야합니다.
Big T Larrity

코드 스 니펫은 '코드'가 아닙니다. '어떤 코드가 더 좋은지'물어 보면 아마추어처럼 보입니다.
Miles Rout 2018 년

1
나는 아마추어입니다 나와 함께 먹으 렴 미세 감사 마일 그래서
빅 T Larrity

답변:


25

일반적으로 데이터 범위를 최대한 좁혀서 범위를 넓히고 범위를 넓혀야한다는 것을 알게되었습니다. 즉 , 멤버 대신 로컬 변수로 만들 있다면 시작해야 할 것입니다.

범위가 좁을수록 코드에서 해당 데이터에 대해 추론해야하는 장소 수가 줄어들 기 때문에 잘못 추론 할 수있는 장소 수가 줄어들 기 때문입니다 (버그로 이어짐).

실제로 로컬 변수 만 선언 해도 실제로 성능 문제가되지는 않습니다. 싸고 최신 컴파일러는 "extras"를 최적화 할 수도 있습니다.

그것들을 초기화하는 것이 문제가 될 수 있습니다. 귀하의 경우 강체는을 통해 매번 조회되며 GetComponent, 이는 0이 아닌 비용입니다. 이 특정 게임 오브젝트에 대해 강체 구성 요소가 변경되지 않는다는 것을 알고 있다면 한 번 찾아서 멤버 변수에 결과를 저장하고 호출 당 약간의 오버 헤드를 피할 수 있습니다.

이 경우에는 통화 당 오버 헤드가 크지 않을 것 같지만 시간이 지남에 따라 많은 구성 요소에 대해이 작업을 수행하면 결과가 더해질 수 있습니다. 확실하게 프로파일 러를 적용하고 싶을 것입니다.

요약하자면, 일반적으로 기본적으로 가능한 한 로컬로 설정하는 것이 좋지만,이 경우 rb멤버 를 만들어 한 번에 조회 Awake를 수행하고 매번 FixedUpdate호출 하지 않아도 되도록 멤버 를 만드는 것이 합리적 입니다.


1
Josh에게 감사합니다. rb를 한 번만 초기화하는 것이 더 좋을 것이라고 생각했으며 그 이유를 분명히 설명해 주셔서 대단히 감사합니다. GetComponent가 매번 초기화하는 것으로 100 % 확신하지 않았거나 Monobehaviour에서 단순히 '찾아 보는'것이 100 % 확실하지 않다는 것을 알면 기쁩니다. 하지만 지금은 그것에게 슈퍼 빠른 도움이 답변에 대한 많은 감사를 얻을
빅 T Larrity에게

1
@SuperMegaBroBro GetComponent 매우 빠릅니다. 속도가 비슷한 모든 종류의 조회를 수행하기가 어렵습니다. 문제를 시사하는 성능 데이터가 없으면 "로컬을 유지"접근 방식을 사용하십시오. 나중에 언제든지 최적화 할 수 있습니다. answers.unity.com/questions/185164/…를 참조하십시오. 캐싱도 무료가 아님을 잊지 마십시오. GetComponent게임에서 모든 것을 캐싱 하면 순 손실 이 수 있습니다. 법안. 최적화가 가치가있는 곳을 식별하십시오. 훌륭한 게임을 만드는 데 집중하십시오 :)
Luaan

1
이 답변에서 제외해야 할 주요 요점은 다음과 같습니다. 가장 추론하기 쉬운 코드를 찾고 테스트하고 버그가 없는지 확인하려면 로컬 변수를 사용하십시오. 그러나 항상 그렇듯이 때때로 성능상의 이유로 완벽한 코드를 희생해야하기 때문에 클래스 멤버가 적절할 수 있습니다 (그러나 프로파일 우선, 단순히 조기 최적화를하지는 마십시오).
Polygnome

원래 질문을 쓰는 동안 '캐싱'문제에 대해 궁금해하는 매우 많은 사람들, 특히 Luaan에게 감사드립니다 (그러나 나는 그 말을하는 법을 정말로 몰랐습니다). 가능한 한 '로컬'접근 방식을 취할 것입니다. 평소 친구들과 같이 큰 도움을 주셔서 감사합니다.
Big T Larrity

2

Josh Petrie의 답변은 매우 훌륭합니다. 여기에 보완적인 관점이 있습니다.

도메인을 상당히 잘 이해하는 코드로 작업 할 때 변수의 범위를 변수의 범위에 맞출 수 있습니다.

예를 들어 메소드 가있는 Person클래스 가있는 경우 클래스 waveGoodbyehand객체가 없었기 때문에 로컬에서로 선언 할 수 있습니다 waveGoodbye. 이제 사람이 손을 가지고 있음을 분명히 알 수 있으므로 Person생각하지 않고 자연스럽게 회원으로 선언 할 수도 있지만 동일한 문제가 적용됩니다.

hand로컬로 선언하면 나중에 karateChop손이 필요한 메소드를 추가 할 수 있습니다 . 주니어 개발자는 종종 선언을 복사 / 붙여 넣기로 넘어 가기 때문에 waveGoodbye동일한 개념을 두 지점에 위치 시키기 때문에 변수를 로컬로 선언하는 것이 문제가 될 수 있습니다 . hand그런 다음 변경 사항을 두 곳에서 수정해야하므로 개미 버그 언덕 이 시작됩니다 .

결국,

  1. 신고서의 배치에 확신이있는 경우, 신고 내용의 범위를 적절하게 지정하십시오.

  2. 확신이 없다면 로컬을 시작하고 코드 재사용이 필요할 때 리팩터링해야합니다.

편집 : 아, 그리고 당신의 선언의 범위를 알아내는 데 너무 많은 시간을 소비하는 것과 같은 실수를하지 마십시오. 데이터의 구조를 미리 이해하기 어렵고 코드를 작성할 때 구조 자체를 드러내는 방법이 있습니다.


2
또한 모든이 같은 것들을 자연스럽게, 주문 가진 Person멤버가 있어야 hand 그 관련있는 경우 응용 프로그램에서 종종 다른 개발자 (대부분의 시간 데 도움이 당신이 더 나은 코드를 이해 6 개월 후를). 이 경우 성능을 저하시키는 경우에도 Rigidbody귀하의 회원으로 가입 Player하는 것이 좋습니다. 비디오 게임에서 고려해야 할 관련 포인트입니다,하지만 내가 생각하는 코드를 명확하게하는 것이 종종 더 중요하다,
alseether

1
훌륭한 답변 감사합니다. 나는 아는 것처럼 들리려고 노력하지는 않지만이 모든 대답은 이미 내가 생각했던 것을 다시 확인 했으므로 한 번은 매우 행복하고 내 게임에서 멋진 발전을 이루었습니다. 지금은 적절한 애니메이션과 모든 것을 갖춘 3D 축구 게임을 만들고 있으며 실제 걸음을 내딛고 있습니다. 곧 D 플레이어를 만드는 방법에 대한 도움이 필요합니다.
Big T Larrity
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.