https://vimeo.com/28353283

반응형

http://www.unrealengine.com/html5/


파이어폭스가 필요한듯 하네요


언리얼이... 아.............. .나 ㅡ.ㅡ;;;


유니티~~ 유니티~~~~ 응?

반응형





캐릭터

UE3를 활용하여 자신의 프로젝트에 맞는 캐릭터를 구현하기에 앞서 UE3에 이미 구현되어 있는 캐릭터 작동 방식을 분석하기로 한다. 그리하여 캐릭터 구현에 필요한 기능이 중복구현됨을 막고 효율적으로 UE3에 통합될 수 있도록 한다.

여기서 살펴볼 내용은 Core기능에 해당하는 AnimTree, AnimSet, Morph 등의 기능이 아니라, 로직에 해당하는 Pawn, PlayerController, PlayerReplicationInfo 등의 오버뷰와 이들이 엔진 내 어떤 포지션에 해당하는지를 중점으로 살펴본다.

캐릭터 Bone 구조

분석 요소

UE3에서 캐릭터를 구현하는데 필요한 요소들을 살펴본다.

Pawn

  • 특징
    • Actor→Pawn 상속
    • player 나 AI 가 컨트롤하기 위한 Base Actor 클래스에 해당한다.
    • mesh, collision, physics 등의 기능이 있고, 데미지를 주며 소리를 내고 무기나 다른 소지품을 들고 다니며, 월드상 다른 Pawn 과의 물리적 인터렉션 등을 담당한다.
  • 기능
    • 캐릭터가 돌아 다닐 수 있는 floor 에 대한 성격을 정의한다.
      • Pawn 이 서있는 지면의 Normal ( Floor, PHYS_Spider, PHYS_Walking 에서만 쓰인다. )
      • 올라갈 수 있는 floor 높이를 정의. ( MaxStepHeight, MaxJumpHeight )
      • 내려갈 수 있는 floor 높이를 정의. ( LedgeCheckThreshold )
      • 이동 가능한 floor 경사면 값 지정. ( WalkableFloorZ, 이는 floor 의 normal 벡터와 UpVector 를 내적한 스칼라 값 이며 Pawn은 기본적으로 0.7 (~= 45 degree) 로 초기화 되어 있다. )
      • 상기 3가지 사항은 캐릭터 이동 및 PathFinding 등에 활용된다.
    • 모든 Pawn을 링크드리스트로 관리. ( NextPawn, 월드 상 모든 Pawn 순회에 용이하다. )
    • Crouch 관련 정보 정의 가능
      • 웅크릴 수 있다. ( bCanCrouch )
      • 웅크리길 원한다. ( bWantsToCrouch )
      • 웅크린 상태이다. ( bIsCrouched )
      • 다시 일어서고 싶다. ( bTryToUncrouch )
      • Crouch 시, 실린더 정보 ( CrouchHeight, CrouchRadius )
      • 웅크리기 & 일어서기 이벤트 함수 제공.
        // APawn::performPhysics 로부터 호출
        void APawn::Crouch(INT bClientSimulation)
        {
            ...
        }
         
        void APawn::UnCrouch(INT bClientSimulation)
        {
            ...
        }
    • 이동 목적지에 다다르면 smooth하게 속도를 줄이면서 멈춘다. ( bReducedSpeed )
    • 여러 행위들에 대한 플래그
      • 점프기능이 있다. ( bJumpCapable )
      • 점프할 수 있다. ( bCanJump )
      • 데미지 입을 수 있다. ( bCanBeDamaged )
      • 웅크릴 수 있다. ( bCanCrouch )
      • 날 수 있다. ( bCanFly )
      • 수영할 수 있다. ( bCanSwim )
      • 텔레포트할 수 있다. ( bCanTeleport )
      • 걸을 수 있다. ( bCanWalk )
      • 사다리에 오를 수 있다. ( bCanClimbLadders )
      • 횡이동 할 수 있다. ( bCanStrafe )
      • 이 밖에 다양한 플래그 들 ( bAvoidLedges, bStopAtLedges, bAllowLedgeOverhang, bSimulatedGravity, bIgnoreForces, bCanWalkOffLedges, bCanBeBaseForPawns, bSimGravityDisabled, bDirectHitWall, bPushesRigidBodies, bForceFloorCheck, bForceKeepAnchor )
      • 곧 Pawn 에서 제거될 것 같은? 플래그 들 ( bCanMantle, bCanClimbUp, bCanClimbCeilings, bCanSwatTurn, bCanLeap, bCanCoverSlip )
    • AI 관련 변수
      • 성별 ( bIsFemale )
      • 아이템을 집을 수 있다. ( bCanPickupInventory )
      • AI가 날 무시하게 할 수 있다. ( bAmbientCreature )
      • 소리를 들을 수 있다. ( bLOSHearing )
      • 벽을 통해 들려오는 숨죽인 소리를 들을 수 있다. ( bMuffledHearing )
      • 게임 시작 시 controller 에 의해 소유되지 않도록 한다. vehicle 들은 게임 시작 시 controller 에 의해 선점되면 안되겠지.. ( bDontPossess )
      • 난 움직일 수 없다. ( bStationary )
      • 무기 사용할 수 없다. ( bNoWeaponFiring )
      • 뭔가를 사용할 수 있다. ( bCanUse )
      • 이 밖에 다양한 플래그 들 ( bModifyReachSpecCost, bModifyNavPointDest, bPathfindingsAsVehicle, )
      • Path Finding 관련
        • 내가 길을 찾는 방법 ( PathSearchType )
        • 기타 관련 변수 들 ( PathConstraintList, PathGoalList )
      • 들을 수 있는 거리 ( HearingThreshold )
      • 소리를 들을 수 있는 각성도 ( Alertness, -1 ~ 1 사이의 값으로써 높을 수록 소리를 더 잘 들을 수 있다. )
      • 시야 거리 ( SightRadius )
      • 시야 각 ( PeripheralVision, degree 의 cosine 값, default 로 -0.75 ~= 140 도 )
      • 물리적 업데이트할 모니터링 시간 ( AvgPhysicsTime, AI 가 목적지로 가기 위해 업데이트할 시간? 구불구불하게 가거나 똑바로 가게 하는 등의 처리를 위한 변수 )
    • 이동 관련 속성
      • 희망 무브먼트 속도 ( DesiredSpeed & MaxDesiredSpeed, GroundSpeed 에 곱해지므로 실질적으로 Pawn 의 전체적 무브먼트 스피드라고 보아도 무방 )
        // Pawn.uc
        defaultproperties
        {
            ...
            DesiredSpeed=+00001.00000
            ...
        }
         
        // UnController.cpp
        void AController::MoveTo( ... )
        {
            ...
            Pawn->DesiredSpeed = Pawn->MaxDesiredSpeed;
            ...
        }
         
        void AController::MoveToward( ... )
        {
            ...
            Pawn->DesiredSpeed = Pawn->MaxDesiredSpeed;
            ...
        }
         
        // UnPhysic.cpp
        FLOAT APawn::MaxSpeedModifier()
        {
            ...
            if ( !IsHumanControlled() )
            {
                Result *= DesiredSpeed;  // 사람이 조종하지 않는 녀석에 한해서만 적용
            }
            ...
        }
      • 가장 가까운 path ( Anchor )
      • nav mesh 인덱싱 ( AnchorItem, 헌데 사용되지는 않음 )
      • 최근에 도달한 가까운 path ( LastAnchor )
      • 마지막 path finding 실패 시기 ( FindAnchorFailedTime, FindPath() 함수 시도가 실패한 마지막 시간 )
      • 마지막 유효 path 발견 시기 ( LastValidAnchorTime )
      • 도착점 offset ( DestinationOffset )
      • 루트상 다음 지점의 반지름 ( NextPathRadius )
      • 구불구불 이동
        • 방향 ( SerpentineDir )
        • 거리 ( SerpentineDist )
        • 시간 ( SerpentineTime, 구불구불 이동 시 횡이동 시도하기 전까지 직진할 시간 )
    • 물리?
      • Pawn 의 질량 ( Mass )
        // Pawn.uc
        function CrushedBy( Pawn OtherPawn )
        {
            TakeDamage(
                ( 1 - OtherPawn.Velocity.Z / 400 ) * OtherPawn.Mass / Mass,   // 데미지, 위에서 내리누를 때 상대방과의 질량에 대비하여 데미지를 가감하는 용도.
                OtherPawn.Controller,                                         // 유발자 Controller
                Location,                                                     // HitLocation
                vect( 0, 0, 0 ),                                              // Momentum
                class'DmgType_Crushed' );                                     // 데미지 타입
        }
         
        event TakeDamage( ... )
        {
            ...
            momentum = momentum / Mass;     // 데미지가 가해질 때 전해진 충격량으로부터 움직일 속도를 구함. F=ma -> a=F/m
            ...
        }
      • 수영할 때 적용할 물 부양성 ( Buoyancy, 1=자연스러운 부양성 0=no부양성 )
        // UnPhysic.cpp
        void APawn::CalcVelocity( ... )
        {
            ...
            if ( bBuoyant )
            {
                Velocity.Z += GetGravityZ() * DeltaTime * ( 1.f - Buoyancy );  // Buoyancy 가 0 이면 중력을 그대로 적용한다.
            }
            ...
        }
      • 밀리어택 최대거리 ( MeleeRange, 일반적인 밀리어택이 아니라 이동하는 도중 목적지까지의 거리를 가늠하는데 사용하는 것 같음 )
    • 일반
      • 스폰 시간 ( SpawnTime, 스폰 후 일정시간동안 데미지 감소따위를 하는 데 사용. 관련변수 UTGame.SpawnProtectionTime )
      • view pitching 제한 ( MaxPitchLimit )
    • 무브먼트
      • controller 없이도 physics 돌려라~ ( bRunPhysicsWithNoController, acceleration 이 아닌 velocity 에 의해서만 움직이게 되겠다. )
      • 풀 악셀 ( bForceMaxAccel, 기존 acceleration 무시하고 풀악셀로 최대 velocity 를 이끌어 낸다. )
      • 최대 지형 이동 속도 ( GroundSpeed )
      • 최대 수영 이동 속도 ( WaterSpeed )
      • 최대 활강 이동 속도 ( AirSpeed )
      • 최대 등반 이동 속도 ( LadderSpeed )
      • 가속 비율 ( AccelRate, 이것이 곱해져 acceleration 을 구한다. )
      • 점프 속도 ( JumpZ, 수직 up 방향 속도 )
      • 수중 이탈 속도 ( OutofWaterZ, 점프로 물 밖으로 이탈할 때 z up 방향 속도. 물 근처 난간위로 올라가는 것을 보장하기 위해 설정하는 값인듯 )
        // Pawn.uc
        function JumpOutOfWater( vector jumpDir )
        {
            ...
            velocity.Z = OutofWaterZ;  // set here so physics uses this for remainder of tick
            ...
        }
      • 수중 이탈 가능 높이 ( MaxOutOfWaterStepHeight, 수영하며 수중이탈 가능한올라갈 수 있는 높이 )
      • 낙하 최대 가속도 제한할까? ( bLimitFallAccel )
      • 공중에서의 컨트롤 시간 factor ( AirControl, acceleration 을 이 시간만큼 적용한 후 테스트하는 용도 )
        // UnPhysic.cpp
        void APawn::physFalling( FLOAT deltaTime, INT Iterations )
        {
            ...
            if ( !bDoRootMotion && TickAirControl > 0.05f )
            {
                // 현재 velocity 에 TickAirControl 시간만큼 경과 후 delta velocity 까지 더한 후 이동거리를 체크한다.
                FVector TestWalk = ( TickAirControl * AccelRate * Acceleration.SafeNormal() + Velocity ) * deltaTime;
                TestWalk.Z = 0.f;
                ... // 이후는 현재 Location 으로부터 TestWalk 만큼 이동한 곳에 특정 world 오브젝트가 있는지 (지형 포함) 체크한다.
            }
            ...
        }
      • 걷기&웅크리기 속도 퍼센티지 ( WalkingPct & CrouchedPct, 기본 이동 속도에 곱하여 걷기속도 및 웅크리기속도를 구하는 방식에 사용 )
        // UnPhysic.cpp
        FLOAT APawn::MaxSpeedModifier()
        {
            ...
            if ( bIsCrouched )
            {
                Result *= CrouchedPct;
            }
            else if ( bIsWalking )
            {
                Result *= WalkingPct;   // 바로 위에서 Pawn 의 무브먼트 속도를 Result 에 누적하여 구하고 그것을 Walking 상태여부에 따라 곱하여 현재 무브먼트 속도를 구한다.
            }
            ...
        }
      • 데미지 없이 낙하 가능한 속도 ( MaxFallSpeed, velocity 와 비교된다. )
      • AI들은 이보다 적은 낙하속도가 가능한 길을 택할 것이다. ( AIMaxFallSpeedFactor, 바로 위 변수와 곱하여 AI를 위한 낙하 속도를 구함 MaxFallSpeed * AIMaxFallSpeedFactor )
    • Camera 관련
      • Pawn 카메라 높이 ( BaseEyeHeight )
        // UnPawn.cpp
        FVector APawn::GetPawnViewLocation()
        {
            return Location + FVector( 0.f, 0.f, 1.f ) * BaseEyeHeight;
        }
      • 계산된/조절된 Pawn 카메라 높이 ( EyeHeight )
    • 숨쉬기/HP
      • 숨을 쉬기 위한 머리 ( HeadVolume )
      • HP ( Health )
      • 최대 HP ( HealthMax )
      • HP 를 모든 클라에게 복제할까? ( bReplicateHealthToAll )
      • 숨쉬기 타이머 ( BreathTime, 물에 빠졌을 때 일정 시간마다 데미지를 주기 위한 주기 )
        // UnLevTic.cpp
        void APawn::TickSpecial( FLOAT DeltaSeconds )
        {
            // Authority 이고 BreathTime 중이라면
            if ( Role == ROLE_Authority && BreathTime > 0.f )
            {
                BreathTime -= DeltaSeconds;
         
                if ( BreathTime < 0.001f )
                {
                    // 때가 됐다면 BreathTimer 호출 (바로 아래)
                    BreathTime = 0.0f;
                    eventBreathTimer();
                }
            }
         
            ...
        }
         
        // Pawn.uc
        event BreathTimer()
        {
            if ( HeadVolume.bWaterVolume )
            {
                if ( Health < 0 || WorldInfo.NetMode == NM_Client || DrivenVehicle != None )
                    return;    // 죽었거나 클라이언트거나 무엇인가를 타고있다면 무시
         
                TakeDrowningDamage();    // 익사 피해
         
                if ( Health > 0 )
                    BreathTime = 2.0;    // 2초 후 다시 BreathTimer 호출
            }
            else
            {
                BreathTime = 0.0;        // 더 이상 피해는 없음
            }
        }
      • 얼마만큼 숨을 참을 수 있는가? ( UnderWaterTime, 최초 입수 시 BreathTime 에 대입되는 값. 이 시간이 지나면 위의 BreathTimer 함수에 나와있는대로 2초마다 데미지 )
        // UTPawn.uc
        event HeadVolumeChange( PhysicsVolume newHeadVolume )
        {
            ...
         
            else if ( ... )
            {
                BreathTime = UnderWaterTime;    // 입수 시 숨쉬기 타이머 발동
            }
        }
         
        defaultproperties
        {
            ...
            UnderWaterTime=+00020.000000    // 20초
            ...
        }
      • 마지막으로 피해를 입은 시간 ( LastPainTime, BOT 의 경우 피격받고 일정 시간동안 Aim 을 불안정하게 하기위한 용도로써 활용된다. )
        // Pawn.uc
        function PlayHit( ... )
        {
            ...
            LastPainTime = WorldInfo.TimeSeconds;
        }
    • 루트모션
      • 루트모션 속도 ( RMVelocity, 클라이언트에서 루트모션을 재현하기 위한 용도의 변수. 또는 Controller.bPreciseDestination정확한 이동 기능이 활성화일 때 사용되기도 함. )
      • 강제 루트모션 속도 사용 ( bForceRMVelocity, 이 값이 true 면 APawn::CalcVelocity() 에서 RMVelocity 값을 직접적으로 사용 )
        // UnPhysic.cpp
        void APawn::CalcVelocity( ... )
        {
            ...
            if ( bForceRMVelocity )
            {
                Velocity = RMVelocity;
                return;
            }
            ...
        }
      • 강제 일반적인 속도계산 ( bForceRegularVelocity, 이 값이 true 면 APawn::CalcVelocity() 에서 RMVelocity 값을 절대로 사용하지 않는다. )
    • 사운드와 노이즈
      • 여러 변수들 ( noise1spot, noise1time, noise1other, noise1loudness, noise2spot, noise2time, noise2other, noise2loudness )
      • 사운드 음 꺾기 ( SoundDampening )
    • 데미지
      • 데미지 증가 ( DamageScaling ) *

Controller

PlayerController

PlayerReplicationInfo

UTGame 관련

샘플로 제공되는 언리얼토너먼트3 (이하 UTGame) 의 캐릭터를 구현하는데 활용된 여러 요소들을 추가적으로 살펴본다.

UTFamilyInfo

UTPlayerReplicationInfo

이동

정확한 이동

엔진에서 목표지점destination까지 정확하게 이동시켜주는 로직이 존재한다.

대략적인 방법은 이렇다.

  1. 정확히 도달해야 하는 목표지점을 설정한다. (by controller)
  2. 매 프레임마다 도착했는지 여부를 검사하고 아직 도달하지 못했다면 적절한 velocity 를 계산한다.
  3. 목표지점destination에서의 허용 Offset 안에 도달하면 이벤트함수를 호출한다. ( Controller.ReachedPreciseDestination() )

관련 변수/함수는 아래와 같다.

  • 변수
    // Pawn.uc
    var float             DestinationOffset;          // 목표지점으로부터의 허용 Offset
     
    // Controller.uc
    var bool              bPreciseDestination;        // 목표지점에 맞는 velocity 를 강제할 것인지의 여부, 정확한 이동을 수행할 것인지 여부와 상통
    var BasedPosition     DestinationPosition;        // 목표지점
  • 함수
    // UnPhysic.cpp
    void Pawn::CalcVelocity( ... )
    {
        ...
        // RooMotion 일 경우를 제외하고 '정확한 이동' 처리를 수행한다.
        if ( !bDoRootMotionAccel && Controller && Controller->bPreciseDestination )
        {
            FVector Dest = controller->GetDestinationPosition();   // Controller.DestinationPosition 을 Vector 로 형변환하여 리턴
            if ( ReachedDestination( Location, Dest, NULL ) )
            {
                Controller->bPreciseDestination = FALSE;           // '정확한 이동'을 종료
                Controller->eventReachedPreciseDestination();      // 종료 이벤트 호출
     
                Velocity = FVector( 0.f );
                Acceleration = FVector( 0.f );
            }
            else if ( bForceMaxAccel )
            {
                const FVector Dir = (Dest - Location).SafeNormal();
                Acceleration      = Dir * MaxAccel;
                Velocity          = Dir * MaxSpeed;
            }
            else
            {
                Velocity = (Dest - Location) / DeltaTime;
            }
            ...
        }
        ...
    }
     
    // UnPawn.cpp
    UBOOL APawn::ReachedDestination( ... )
    {
        ...
     
        return ReachThresholdTest( ... );
    }
     
    UBOOL APawn::ReachThresholdTest( ... )
    {
        ...
        FLOAT Threshold = ThresholdAdjust + CylinerComponent->CollisionRadius + DestinationOffset;    // 도착으로 인정할 유효 반지름을 계산
        ...
        if ( Dir.SizeSquared() > Threshold * Threshold )
            return FALSE;
        ...
        // 적절하게 테스트하고
        return TRUE;        // 도착했다고 판정
    }

상기 APawn::ReachThresholdTest 함수의 동입부에 도착지점으로부터의 허용 반지름을 계산하는 부분이 있는데, 이 값에 음수를 주어 좀 더 정확한 목표지점에 도달하게 할 수 있다.

무브먼트

언리얼엔진3에 기본적으로 제공되는 UTGame 을 기반으로 한 분석내용이다.

웅크리기 Crouch

코드플로우

  • 발생
    1. DefaultInput.ini
      • .Bindings=(Name=“C”,Command=“GBA_Duck”)
      • .Bindings=(Name=“GBA_Duck”,Command=“Duck | onrelease UnDuck | Axis aUp Speed=-1.0 AbsoluteAxis=100”)
    2. simulated exec function Duck() (UTPlayerInput.uc)
      • bDuck = true;
  • 루프1
    1. state PlayerWalking::ProcessMove(…) (PlayerController.uc) ← state PlayerWalking::ProcessMove(…) (UTPlayerController.uc) ← state PlayerWalking::PlayerMove(float DeltaTime) (PlayerController.uc) ← state PlayerWalking::PlayerMove(float DeltaTime) (UTPlayerController.uc) ← event PlyaerTick(float DeltaTime) (PlayerController.uc) ← event PlayerTick(float DeltaTime) (UTPlayerController.uc)
      • CheckJumpOrDuck();
    2. function CheckJumpOrDuck() (UTPlayerController.uc)
      • 점프나 더블점프를 수행하는 함수를 호출
      • Pawn.ShouldCrouch(bDuck != 0);
    3. funciton SouldCrouch( bool bCrouch ) (Pawn.uc)
      • bWantsToCrouch = bCrouch;
  • 루프2
    1. AActor::TickAuthoritative ← AActor::Tick ← APawn::Tick ← TickActors<FDeferredTickList::FGlobalActorIterator>
      • performPhysics 호출
    2. APawn::performPhysics(float DeltaSeconds) (UnPhysic.cpp)
      • 적절한 조건을 체크한 후 (bWantsToCrouch, bIsCrouched 따위) Crouch() 나 UnCrouch() 를 호출
    3. APawn::Crouch(INT bClientSimulation) (UnPawn.cpp)
      • Collision Cylinder 의 반지름과 높이를 CrouchRadius 와 CrouchHeight 로 변경
      • Crouch Collision Cylinder 가 더 커졌다면 지면을 침범했는지 체크한다.
      • eventStartCrouch( 높이차이 ) 호출
    4. simulated event StartCrouch(float HeightAdjust) (UTPawn.uc)
      • Super.StartCrouch(HeightAdjust);
      • CrouchMeshZOffset = HeightAdjust;
    5. simulated event StartCrouch(float HeightAdjust) (Pawn.uc)
      • EyeHeight 조절
      • OldZ 조절
      • BaseEyeHeight 조절

특이사항

  • 웅크리기에 사용될 충돌영역 정보인 CrouchRadius, CrouchHeight 를 세팅해야 한다.
  • 이때 MaxStepHeight 가 CollisionHeight - CrouchHeight 보다는 커야 한다. MaxStepHeight 는 캐릭터가 자연스럽게 이동 가능한 최대 허용높이이다. 웅크리기가 발동되면 내부적으로 캐릭터 바운딩실린더 높이를 조절하는데 그 갭이 MaxStepHeight 보다 크면 캐릭터는 Falling 운동을 하게끔 처리된다. (엔진 내부적으로) 때문에 주의가 필요하다.

점프 Jump

코드 플로우

  1. 발동
    // DefaultInput.ini
    .Bindings=(Name="GBA_Jump",Command="Jump | Axis aUp Speed=+1.0 AbsoluteAxis=100")
  2. 플래그 체크
    // UTPlayerInput.uc
    exec function Jump()
    {
        ...
        Super.Jump();
        ...
    }
     
    // PlayerInput.uc
    exec function Jump()
    {
        ...
        bPressedJump = true;
    }
  3. 지연 점프
    // PlayerController.uc
    state PlayerWalking
    {
        ...
        function PlayerMove( float DeltaTime )
        {
            ...
            // 지금 점프할 수 없는 상황이면 지연시킨다.
            if ( bPressedJump && Pawn.CannotJumpNow() )
            {
                bSaveJump = true;
                bPressedJump = false;
            }
            ...
        }
        ...
    }
  4. 점프 시도여부 체크 (매 프레임)
    // UTPlayerController.uc
    function CheckJumpOrDuck()
    {
        ...
        else if ( bPressedJump )
        {
            Pawn.DoJump( bUpdateing );
        }
        ...
    }
     
    // PlayerController.uc
    function CheckJumpOrDuck()
    {
        if ( bPressedJump && (Pawn != None) )
        {
            Pawn.DoJump( bUpdating );
        }
    }
  5. 실제 점프로직 처리
    // UTPawn.uc
    function bool DoJump( bool bUpdating )
    {
        ...
        if ( Physics ==PHYS_Spider )
            Velocity = JumpZ * Floor;
        else if ( Physics == PHYS_Ladder )
            Velocity.Z = 0
        else if ( bIsWalking )
            Velocity.Z = Default.JumpZ;
        else
            // 보통 이부분에 걸린다.
            Velocity.Z = JumpZ;
        ...
    }

부가기능

TurnInPlace

Pawn 의 현재 Rotation 을 기준으로 좌우 일정 반경을 회전할 동안 발이 땅에 접지한 상태로 있는 기능을 지원한다. UnrealEngine3 에서는 이 기능을 Turn-In-Place 라고 지칭한다. 이를 수행하는 레이어는 UDKPawn 이다.

분석 포인트

  • AnimTree 노드 캐싱
    // UTPawn.uc
    simulated event PostInitAnimTree(SkeletalMeshComponent SkelComp)
    {
        ...
        // 허리쪽 Bone 을 제어하는 컨트롤 캐싱 (RootRot 이란 이름을 가진 SkelControlSingleBone 컨트롤)
        RootRotControl = SkelControlSingleBone( mesh.FindSkelControl( 'RootRot' ) );
        ...
        // 조준 노드 캐싱
        AimNode = AnimNodeAimOffset( mesh.FindAnimNode( 'AimNode' ) );
        ...
    }
  • 업데이트 로직
    // UDKPawn.cpp
    void AUDKPawn::TickSpecial( FLOAT DeltaSeconds )
    {
        ...
        // 현재 Aim pitch 와 yaw 를 얻는다.
        INT PawnAimPitch;
        if ( Controller )
        {
            // 컨트롤러의 Pitch를 얻는다.
            PawnAimPitch = Controller->Rotation.Pitch;
        }
        else
        {
            // Pawn 의 Pitch를 얻는다.
            PawnAimPitch = Rotation.Pitch;
     
            if ( PawnAimPitch == 0 )
            {
                PawnAimPitch = RemoteViewPitch << 8;
            }
        }
     
        // Pawn 의 최종 조준 Pitch
        PawnAimPitch = UnwindRot( PawnAimPitch );
     
        INT PawnAimYaw = UnwindRot( Rotation.Yaw );
        // Pawn 의 최종 조준 Yaw (가 될 값)
        INT AimYaw = 0;
     
        if ( Physics == PHYS_Walking && Velocity.Size() < KINDA_SMALL_NUMBER )
        {
            // PawnAimYaw 는 손이 향하는 방향, RootYaw 는 발이 향하는 방향이라 생각하면 이해가 쉽다.
            INT CurrentAimYaw = UnwindRot( PawnAimYaw - RootYaw );
            INT RootRot = 0;
     
            if ( CurrentAimYaw > MaxYawAim )
            {
                RootRot = ( CurrentAimYaw - MaxYawAim );
            }
            else if ( CurrentAimYaw < -MaxYawAim )
            {
                RootRot = ( CurrentAimYaw - (-MaxYawAim) );
            }
     
            RootYaw += RootRot;
            RootYawSpeed += ( (FLOAT)RootRot ) / DeltaSeconds;
     
            // 최종 손과 발의 offset. 이것이 곧 Aim 노드에 적용될 Yaw
            AimYaw = UnwindRot( PawnAimYaw - RootYaw );
        }
        else
        {
            RootYaw = Rotation.Yaw;
            RootYawSpeed = 0.f;
            AimYaw = 0;
        }
     
        // 좌우 90 도 회전을 각각 -1, 1 로 매핑시킨 값으로 변환
        if ( !bNoWeaponFiring )
        {
            CurrentSkelAim.X = Clamp<FLOAT>( ( (FLOAT)AimYaw / 16384.f ), -1.f, 1.f );
            CurrentSkelAim.Y = Clamp<FLOAT>( ( (FLOAT)PawnAimPitch / 16384.f ), -1.f, 1.f );
        }
     
        // 허리를 Aim 의 반대쪽으로 회전. 즉, 손의 방향이 Pawn Rotation 과 일치하고 발의 방향을 보정하는 방식
        if ( RootRotControl )
        {
            RootRotControl->BoneRotation.Yaw = -AimYaw;
        }
     
        // Aim 업데이트
        if ( AimNode )
        {
            AimNode->Aim = CurrentSkelAim;
        }
        ...
    }

분석

참고

반응형

스크립트에 의한 네이티브코드 생성

개요

UnrealScript 를 사용하다 보면 Native 레이어와 상호 통신을 해야할 필요가 생긴다. 이 때 Script 의 내용을 Native 가 인식할 수 있도록 글루코드를 생성할 필요가 있는데 여기서는 이것에 대해 다뤄보도록 한다.

UnrealScript

스크립트 컴파일

이어지는 설명을 이해하려면 스크립트 컴파일하는 법을 먼저 알아야 한다. 컴파일은 게임 실행파일을 이용한1) 콘솔명령어로 수행되며 거두절미하고 바로 명령어 때려본다.

// 이하 콘솔명령어이며, 실행파일은 UTGame.exe 라고 가정한다.
UTGame.exe make                            // 릴리즈로 빌드
UTGame.exe make -full                      // 릴리즈로 풀 빌드
UTGame.exe make -debug                     // 디버그로 빌드 (스크립트를 디버깅하기 위해)
UTGame.exe make -debug -full               // 디버그로 풀 빌드

Native 글루코드 생성

UnrealScript 에서 Native 코드를 생성하는 키워드는 아래와 같다.

// UTGame/Classes/UTWeapon.uc
class UTWeapon extends UDKWeapon
    native // 이 키워드가 붙으면 Native 글루코드가 생성된다.
    ...

:!: 글루코드가 생성되는 파일명도 지정할 수 있다.

위와 같이 native 키워드 뒤에 아무것도 없다면 [패키지명]+Classes.h 에 글루코드가 생성된다. (위 예제와 같이) UTGame 의 경우 UTGameClasses.h 파일에 AUTWeapon 클래스에 대한 선언이 되어있는 것을 확인할 수 있다.

만약 native( MyWeapon ) 와 같이 괄호 안에 특정 명칭을 넣는다면 [패키지명]+[괄호內명]+Classes.h 에 글루코드가 생성된다. 위의 경우 UTGameMyWeaponClasses.h 에 해당된다.2)

글루코드 등록 및 정의

위와같이 글루코드의 헤더가 생성되면 이제 정의(.cpp)를 하고 등록을 할 차례다.

글루코드 정의

스크립트 내에서 네이티브 함수를 지정하는 방법은 여럿 있지만 여기선 그 설명은 생략하고 클래스와 네이티브 함수를 정의하는 방법에 대해 설명하겠다. (위의 UTWeapon 을 예로들어 계속 설명)

먼저 적당한 .cpp 파일을 만든다. UTWeapon.cpp 라고 파일을 만든 후 그 안의 내용은 아래와 같아야 한다.

// UTWeapon.cpp
#include "UTGame.h"
#include "UTGameMyWeaponClasses.h"    // UTWeapon이 선언된 헤더
 
IMPLEMENT_CLASS(AUTWeapon);           // 클래스의 기본적인 기능들을 정의
 
UBOOL AUTWeapon::Tick( FLOAT DeltaTime, ELevelTick TickType )
{
    ...
}

여기서 핵심은 IMPLEMENT_CLASS 이다. 이것은 엔진 내에서 필요한 기본기능 및 글루코드에 필요한 기능들을 자동으로 정의해주는 매크로이다.

나머지 함수들은 알아서 정의한다.

글루코드 등록

이제 엔진이 알 수 있도록 글루코드를 등록할 차례이다. 복잡한 설명은 생략하고 바로 코드 들어간다.

// UTGame.cpp
 
...
 
#include "UTGameMyWeaponClasses.h"                  // 다른 헤더들을 보고 "여기다 싶은 곳" 에 모두 포함시킨다.
 
...
 
void AutoInitializeRegistrantsUTGame( INT& Lookup )
{
    AUTO_INITIALIZE_REGISTRANTS_UTGAME;
    AUTO_INITIALIZE_REGISTRANTS_UTGAME_MYWEAPON;    // 여기서 등록
    ...
}
 
void AutoGenerateNamesUTGame()
{
    ...
    #include "UTGameMyWeaponClasses.h"              // 여기서 이름 (Name) 등록
    ...
}
 
...
1) 언리얼엔진3로 개발된 게임의 실행파일에 스크립트 컴파일 모듈이 포함되어 있다.
2) 현재(20100909)확인해본 결과, 간혹 헤더파일이 생성되지 않는 경우가 있다. 아마 엔진버그같은데 이럴땐 헤더파일을 수동으로 생성해주고 스크립트 컴파일을 해주면 잘 반영된다.

반응형

 PackageNames.AddItem(TEXT("Sample02_LoadPackage"));

네이티브 패키지 목록에 패키지 추가하기

void appGetGameNativeScriptPackageNames(TArray<FString>& PackageNames, UBOOL bCanIncludeEditorOnlyPackages)
{
...
   PackageNames.AddItem(TEXT("AutoGenExample"));
}

반응형

http://donggas90.blog.me/100141378528



[UDK] 프로그래밍 초보를 위한 언리얼 스크립트 코드 10선

  

이번 포스트는 프로그래밍을 UDK로 처음 접하시는 분을 위해 적어 볼까 합니다.

 

 

먼저 UDK(언리얼 엔진)는 언리얼 스크립트라는 자신들만의 언어를 사용합니다.

 

 

언리얼 스크립트를 위한 비쥬얼 스튜디오 플러그인 엔프린지와

스크립팅을 시작하는 방법에 대해서는 아래 포스트에서 확인하세요.

http://donggas90.blog.me/100127258591

 

 

그리고 짠 언리얼 스크립트를 어떻게 게임과 에디터에 적용하는 지에 대한 정보는

아래 포스트를 확인하세요.

http://donggas90.blog.me/100134298424

 

 

위 두 포스트의 내용을 숙지하셨다는 가정 하에 시작하겠습니다.

 

 

1. 클래스 오버라이드 - extends

 

  class HUD extends Actor;

 HUD.uc의 일부입니다.

 

class는 앞으로 클래스를 선언할 것임을 나타 냅니다.

 

HUD는 이 클래스의 이름을 나타내며, uc파일과 이름이 같아야 합니다. 

 

extends는 이 클래스가 어느 클래스를 오버라이드하고 있는지 가르킵니다.

 

Actor는 extends가 가르키고 있는 클래스 입니다.

 

;는 여기까지 클래스 선언이 끝났음을 알리고 있습니다. 

 

 

오버라이드란 extends가 가르키는 클래스의 모든 내용을 전부 그대로 복사한다는 뜻입니다.

 

복사'당한' 클래스는 부모 클래스가 되고, 복사'받은' 클래스는 자식 클래스가 됩니다.

 

비록 그 내용이 여기 일일이 적혀 있지는 않지만 적혀져 있는 것으로 간주하는 것입니다.

 

 

그리고 또 다른 의미로 '덮어쓴다'는 의미가 있습니다.

 

부모 클래스에 있는 것을 다시 새로 쓸 때, 오버라이드했다고 합니다.

 

 

언리얼 스크립트 파일들을 하나하나 열어 보시면

 

모든 클래스들이 계속해서 다른 클래스를 오버라이드하고 있음을 알 수 있습니다.

 

그리고 그 가장 위에는 Object클래스가 있고 그 바로 밑에는 Actor가 있습니다.

 

즉, 모든 언리얼 스크립트의 시조는 Object입니다.

 

 

 

2. 변수 선언 - var

 

var string A;

var int B;

var(Variable) float C;

var bool D; 

var는 앞으로 변수를 선언할 것임을 나타냅니다. 

 

이것들은 이 변수가 어떤 타입인지 나타 냅니다. 

 

string이란 문자열을 말합니다. 

 

int란 정수를 말합니다. 

 

float이란 실수 말합니다.

 

bool이란 참, 거짓 논리자입니다. 

 

A는 이 변수의 이름이 A임을 나타냅니다.

 

;는 여기까지 변수의 선언이 끝났음을 나타냅니다. 

 

(Variable)란 언리얼 에디터에서 클래스 프로퍼티 창에

 

Variable이라는 카테고리를 만들고 이 변수를 표시하라는 의미이며 

 

반드시 필요하지는 않습니다. 

 

 

이런 방법으로 변수에 이름을 붙여 줄 수 있습니다. 

 

변수의 종류는 더 많지만 일단 이 정도만 알아도 대부분의 데이터 주무르기가 가능합니다.

 

 

변수에 값을 넣는 방법은 아래와 같습니다.

A = "string";

B = 123;

= 1.f;

이것들은 값을 넣어줄 대상입니다.

 

값을 받을 대상은 항상 왼쪽에 위치합니다.

 

=는 왼쪽에 있는 것에 오른쪽 것을 넣는다는 뜻입니다. 

 

일반적으로 사용하는 의미와는 다릅니다. 

 

넣을 대상과 넣어 줄것의 타입이 일치해야 함을 유의하세요. 

 

"string"은 문자열 string을 나타냅니다. " 가 양쪽으로 사용됐음에 유의하세요.

 

123는 정수 123(백이십삼)을 나타냅니다. 

 

별다른 기호를 사용하지 않아도 됩니다. 

 

1.f는 실수 1(일)을 나타냅니다. 

 

언리얼 스크립트에서는 정수와 실수를 구분하기 위해 

 

실수에는 특수한 표기 방법을 사용합니다. 

 

값의 끝에 f를 붙이는 것이 그것입니다.

 

만약 소수점 자리가 없다면 .(온점)과 함께 f를 붙입니다.

 

;는 여기까지 명령이 끝났음을 알립니다. 

 

 

* 심화

var array<int> A;

 

A[0] = 1;

A[100] = 2;

 

배열은 이름은 같은데 다른 번호를 가진 여러 값의 무리입니다.

 

 

 

 

3. 기본값 - DefaultProperties

 

DefaultProperties
{ 

 A = 123

} 

DefaultProperties{ 는 앞으로 기본값 영역이 시작될 것임을 의미합니다. 

 

A의 기본값이 123임을 의미합니다. 여기서 세미콜론(;)은 선택 사항입니다.

 

} 는 기본값 영역이 끝났음을 의미합니다. 

 

 

이렇게 하면 A는 UDK가 시작되면 항상 123일 것입니다. 

 

이런식으로 기본값이 필요할 경우 정의해 줄 수 있습니다.

 

 

* 심화

런타임이 초기화될 때마다 이 영역의 기본값이 로드됩니다.

 

 

4. 함수 - function

 

함수를 선언하는 방법은 아래와 같습니다.

 

function EXAMPLE()

{

A = 123;

}

function{}는 함수 영역을 나타냅니다. 

 

EXAMPLE는 함수의 이름을 나타냅니다.

 

()는 함수에 사용할 인수(파라미터)의 목록입니다. 

 

자세한 내용은 아래에... 

 

A = 123;는 함수에서 할 것입니다. 

 

 

이 함수가 집행되면  A = 123;을 할 것입니다.

 

하지만 재밌는 점은 이렇게 만들더라도 실질적으로 작동은 되지 않습니다.

 

왜냐면 언리얼 엔진이 이 함수를 호출하지 않기 때문입니다.

 

따라서 이 함수를 작동하게 하려면

 

언리얼 엔진이 호출하는 함수 안에서 이 함수를 호출해야 합니다.

 

simulated event Tick(float DeltaTime)
{
 

 EXAMPLE();

} 

대표적인 예로 Tick이라는 이벤트가 있습니다.

 

이 이벤트는 일정 시간 간격으로 계속 이 영역을 집행합니다.

 

그리고 그 시간 간격은 DeltaTime에 실수 타입으로 저장합니다.

 

 

이벤트는 함수와는 성격이 다른데, 이벤트는 모두 언리얼 엔진이 특정 상황이나 조건에서 호출하는 것입니다.

 

임의로 프로그래머가 호출할 수 없습니다.

 

 

 

function EXAMPLE( int B )

{  

A = 25;

A = B;

} 

 

EXAMPLE( 12 ); 

A는 12 

위 스크립트는 인수 사용의 대표적인 예입니다.

 

인수는 함수를 선언할 당시에는 타입만 지정돼 있습니다.

 

뭔가 값은 없습니다.

 

하지만 다른 곳에서 사용되었을 때 그 값을 지정해 주고

 

함수 내용을 집행하게 됩니다.

 

 

 

 

5. 함수의 변수화 - return

 

앞에서 함수에 대해 알아 봤습니다.

 

그런데 함수에서 뭔가 계산한 뒤 바로 무엇인가 얻고 싶을 경우가 생길 겁니다.

 

따로 변수의 도움 없이 말입니다.

 

function int EXAMPLE()

{

A = 123; 

return A; 

} 

 

B =  EXAMPLE();

B는 123 

int로 이 함수는 정수 결과를 출력할 것임을 나타냅니다. 

 

return A; 로 이 함수의 출력 값은 A값임을 알립니다.

 

이렇게 하면 함수 내에서 계산한 값을 또 다른 변수에 넣어주고

 

다시 받아서 B에 할당하는 번거로운 과정이 생략됩니다. 

 

* 심화

function Ex ( out int A )

{

A = B + C ;

return;

}

값을 직접 받지 않고 간접으로 받을 수도 있습니다.

 

 

6. 부모 함수 집행 - super

 

오버라이드는 덮어쓴다는 개념이 있다고 말씀 드렸습니다.

 

덮어쓰게 되면 이전의 것은 없어지고 새로운 것만 작성되게 됩니다.

 

함수 역시 오버라이드할 수 있습니다.

 

그런데 함수를 통째로 다시 쓰지 않고 나만의 새로운 코드만 추가하고 싶을 때가 있습니다.

 

이럴 때 쓰는 것이 super코드입니다.

function EXAMPLE()

{

super(Actor).Example(); 

A = 123;

}

super.Example();로 가장 가까운 부모에 있는 Example()함수를 집행하도록 합니다. 

 

 (Actor)는 선택 사항인데 어느 클래스에 있는 부모 함수를 집행할지 지정합니다.

 

 부모 엑터 클래스의 함수가 집행된 뒤 A=123; 집행되게 됩니다.

 

게임의 기본 틀을 구성하는 함수여서 마음데로 수정이 어렵거나

 

언리얼 엔진이 호출하는 이벤트에 내용을 덧붙이고 싶을 때 아주 유용합니다.

 

 

 

7. 조건부 - if

 

뭔가 조건을 제시하고 그게 맞다면 실행되게 하고 싶을 때가 많을 겁니다.

 

이럴 때 쓸 수 있는 것이 if 코드 입니다.

if ( A == 1 )

{

 B = 1;

} 

else if ( A == 2 )

{ 

B = 2; 

} 

else 

{ 

B = 3; 

} 

이것들은 한 묶음입니다. if와 else는 처음과 끝에 각각 하나만 올 수 있고 

 

else if 는 원하는 만큼 쓸 수 있습니다. 

 

이것이 참이면 그 아래 영역을 집행합니다. 

 

즉, A가 1이면 B는 1이될 겁니다. 

 

여기에 사용되는 논리 판단 기호에 유의하세요. 

 

==는 서로 같은지 비교합니다. 

 

!=는 서로 다른지 비교합니다.

 

이외에 <, >, <=, >=는 일반적인 수학에서 쓰는 그데로입니다. 

 

if는 조건 부분을 무조건 참인지 거짓인지 판단합니다.

else if 는 if의 조건이 거짓일 경우 참인지 거짓인지 판단합니다.

else 는 if 와 else if 의 조건 모두가 거짓이면 집행합니다.

 

 

위에서 적어드린데로 프로그램이 조건을 검사하게 됩니다.

 

조건을 검사하려면 CPU가 계산을 해야하고

 

그러면 리소스가 소모 됩니다.

 

게임을 최적화하려면 if를 남발하지 말고 적절히 else를 이용해야 합니다.

 

 

조건을 검사할 때, 꼭 한 가지가 아니라 여러 가지의 조건을 쓰는 경우가 있습니다.

 

이럴 때 수학에서는 AND, OR라는 표현을 쓰는데

 

프로그래밍에도 이런 개념이 존재합니다.

if ( A == 1 && B == 3 )

{

B = 1;

}

else if ( A == 2 || B == 1 )

{

B = 2;

}

&&(쉬프트 + 숫자 7)는 AND라는 의미입니다.

 

||(쉬프트 + \)는 OR라는 의미입니다.

 

 

덧붙여 이런 것도 가능합니다.

var bool A;

 

A = true;

B = 0;

 

if ( A )

{

B = 1;

} 

 

B는 1 

조건 부분이 참(true)인지 거짓(false)인지 검사하는 것이기 때문에

 

조건 그 자체가 참인 경우도 집행됩니다.

 

* 심화

switch(A) 

{ 

case(1) : 

//A가 1이면 집행합니다. 

break;//으로 집행의 끝을 알립니다. 

 

default: 

//A와 관계 없이 집행합니다.

break; 

} 

 

 

8. 변수의 무리 - struct

 

변수들을 여럿 선언하고 보면

 

이따금씩 서로 관련이 있는 변수인 경우가 있습니다.

 

예를 들면 게임 케릭터의 능력치입니다.

 

힘 변수를 선언하고 지능 변수를 각각 선언한다면

 

관리하기가 쉽지 않겠죠.

 

왜냐면 케릭터가 하나가 아닐테니까요.

 

그리고 새로운 능력치를 추가하려면 대부분의 코드들을 뜯어 고쳐야할 것입니다.

 

이럴 때 필요한 것이 바로 구조체, struct 코드입니다.

struct CharacterInfo

{

var int Strength;

var int Intelligence;

};

struct로 여기부터 구조체를 선언하겠다고 알립니다. 

 

CharacterInfo는 이 구조체의 이름입니다. 

 

var int Strength; 구조체에 포함된 변수입니다. 

 

; 구조체를 선언한 뒤 붙이는 것을 잊지 마세요. 

 

그런데 이걸 어떻게 사용하는 걸까요.

 

<strong></strong>

var CharacterInfo A;

구조체를 선언하면 마치 변수 타입인 것처럼 사용할 수 있습니다.

 

A라는 이름을 가진 CharacterInfo 구조체를 만들었습니다.

 

그렇다면 구조체에 포함된 변수는 어떻게 쓰는 걸까요.

 

A.Strength = 123;

A.Intelligence = 321;

구조체의 이름 뒤에 온점을 붙여 그 속에 포함된 변수를 부를 수 있습니다.

 

 

다른 이름의 같은 구조체가 있습니다.

 

하나의 값을 다른 하나에 넣어 주기 위해

 

포함된 변수를 하나하나씩 불러 할당하고 있습니다.

 

var CharacterInfo A; 

var CharacterInfo B; 

 

A.Strength = B.Strength;

A.Intelligence = B.Intelligence;

물론 이런 방법을 쓸 수도 있지만 

 

굳이 일일이 값들을 불러오지 않아도 됩니다.

 

var CharacterInfo A;

var CharacterInfo B;

 

A = B;

 

 

 

 

9. 메모 - /* **/

 

프로그래밍 언어는 우리가 쓰는 말과는 전혀 다릅니다.

 

그리고 복잡한 함수나 추상적인 이름의 변수를 사용해야 하는 경우가 자주 발생합니다.

 

이를 설명하기 위해 메모, 주석을 달게 됩니다.

/** 수 두 개를 더하는 함수 */

function int Add( int A, int B )

{

C = A + B;

return C;

}

/** */이 부호가 사용된 문자들은 모두 무시됩니다.

 

비쥬얼 스튜디오와 엔프린지를 사용하는 경우

 

Add에 마우스를 올리면 툴팁이 나오는데

 

두번째 줄에 주석의 내용이 표시됩니다.

 

 

* 심화

/** 수 두 개를 더하는 함수

* @param A 더할 첫번째 값

* @param B 더할 두번째 값 */

<strong></strong>

function int Add( int A, int B )

{

C = A + B;

return C;

} 

파라미터마다 개별적인 주석을 달 수도 있습니다. 

 

 

 

10. 디버깅 - `log 

 

버그는 예상치 못한 곳에서 주로 발생합니다. 

 

버그를 해결하는 작업을 디버깅이라 하는데 

 

디버깅을 위해서 사용되는 코드가 있습니다. 

 

바로 `log코드입니다. 

 

`는 1의 왼쪽에 있는 키입니다.

 

쉬프트를 누르면 ~이 되는 키죠.

`log("test");

이런 식으로 사용합니다.

 

괄호안의 내용은 문자열이므로 쌍따옴표를 사용해야 합니다.

 

그런데 이 글자는 어디서 확인하는 것일까요.

 

UDK에서 게임 태스트를 시작합니다.

 

그리고 커멘드라인에 SHOWLOG를 입력하면

 

윈도우 cmd같은 검은 창이 표시됩니다.

 

만약 로그가 정상적으로 집행됐다면

 

그곳에 하얀색 글씨로 test란 글자가 나타날 겁니다.

 

 

이런 단순 문자열 로그는 특정 함수나 조건부가 제대로 동작하는지

 

파악할 때 유용합니다.

 

 

만약 변수 값이 궁금할 때는 어떻게 할까요.

 

그럴 때는 이렇게 합니다.

var int A;

`log("variable is"@A);

@는 문자열을 공백 하나를 넣고 합칠 때 사용합니다.

 

만약 A가 123이면

 

로그창에는 이렇게 나타날 것입니다.

 

variable is 123

 

로그 코드는 디버깅에 효과적이기는 하지만

 

로그 또한 집행하려면 CPU가 계산을 해야 합니다.

 

따라서 디버깅이 끝나면 로그 코드는 지워 주세요.

 

반응형

퍼포스에서 UE3 코드 베이스 싱크를 마치고나면 퍼포스 디포 루트 폴더에 UnrealEngine3 라는 디렉토리가 생길 것입니다.

"UnrealEngine3" 폴더 안에는 다음 디렉토리가 있습니다:

  • Binaries - 이 파일에는 바이너리 오브젝트가 담깁니다. 엔진/게임의 컴파일된 버전, UE3 필수 DLL (DirectX, wx 런타임 등), 에디터 리소스 파일 (아이콘 이미지) 등입니다.
  • Development - 엔진의 모든 소스가 실제로 들어가는 곳으로, 이 폴더 안에는:
    • Build - 저희 CIS(연속 통합 서버) 상에서 여러가지 유형의 빌드를 발송하는 배치 파일을 저장하는 곳입니다. CIS 는 빌드를 검사하여 저희가 빌드 에러를 가급적 빠르게 잡아낼 수 있도록 해 줍니다.
    • Documentation - 문서 파일 저장용 폴더입니다. 저희의 자동 생성 윈도우 도움말 파일(UnrealEngine3.chm)이 여기 저장됩니다. 이 도움말 파일은 언리얼 소스를 빠르게 돌아보는 데 큰 도움이 되는 자료입니다.
    • External - 모든 에픽 외부 라이브러리 소스는 이 폴더에 저장됩니다. libPNG, wxWidgets, zlib, Cg 등입니다.
    • Intermediate - 모든 중간 빌드 파일은 여기 저장됩니다. .obj 파일, 미리컴파일된 헤더 등입니다.
    • Src - 소스 파일과 프로젝트 메이크파일용 폴더입니다. 주요 UnrealEngine3 솔루션은 이 폴더에 있습니다. 솔루션 안에는 각 프로젝트에 대한 폴더 역시 있습니다. 예제 프로젝트는 다음과 같이 나뉘어 있습니다:
      • Game 폴더
        • 프로젝트의 루트 폴더 안에는 프로젝트의 비주얼 스튜디오 프로젝트 파일이 있습니다.
        • Classes - .uc (UnrealScript) 파일을 담는 폴더입니다.
        • Inc - .h 파일을 담는 폴더입니다.
        • Src - .cpp 파일을 담는 폴더입니다.
    • Tools - 다양한 엔진 관련 툴에 대한 소스가 모두 저장된 폴더입니다. UDE 비주얼 스튜디오 매크로나 명령줄 툴같은 것들입니다.
  • Engine/Game 폴더 - Binaries 와 Development 폴더 다음에는 Engine 에 대한 폴더가, 그 이후 엔진을 사용하는 각 게임에 대한 폴더가 하나씩 있습니다.
    • Config - 해당 게임에 사용된 세팅을 저장하는 데 사용된 .ini 파일을 담습니다.
    • Content - 해당 게임용 콘텐츠 패키지를 담는 폴더입니다.
    • Localization - 해당 게임용 현지화 텍스트를 담는 폴더입니다.
    • Logs - 해당 게임 실행시 생성되는 로그 파일을 담는 폴더입니다.
    • Script - 해당 게임에 대한 컴파일된 UnrealScript 코드(.u 파일)를 담습니다.

프로젝트 구조


UE3 는 여러 프로젝트로 나뉘는데, 시스템을 분리하고 크로스-플랫폼 호환성을 쉽게 유지할 수 있도록 하기 위해서입니다.

기본 구조는 (최하위 레벨 코드에서 최상위 레벨까지) 다음과 같습니다:

  • Core
  • Engine
  • Editor
  • UnrealED

참고로 이 프로젝트 모두는 서로의 위에 빌드됩니다. 즉 Engine 은 Core 에 의존, Editor 는 Engine 에 의존, UnrealED 는 Editor 에 의존합니다.

  • Core: Core 는 최하위 레벨 클래스로, 문자열 클래스, 배열 클래스, 메모리 매니저와 같은 것들입니다. 말 그대로 핵심 스크립팅 및 로딩 코드가 있는 곳입니다.

  • Engine: Engine 은 대부분의 렌더링과 게임플레이 코드가 있는 곳입니다. 액터, 충돌 감지는 물론 여러가지 서브시스템에 관련된 코드도 포함되어 있습니다. 대부분의 '게임 인터페이스' 코드가 있는 곳입니다.

  • Editor: Editor 는 에디터가 실행중일 때만 실행되는 클래스와 루틴으로 구성됩니다. 사용자가 폴리곤, 브러시, 터레인을 조작 및 보통 게임내에서는 할 수 없는 다른 작업을 할 수 있도록 해 주는 클래스입니다.

  • UnrealED: UnrealED 는 에디터의 실제 UI 구현으로, 에디터 어플리케이션 코드 전부가 있는 곳입니다. 현재 저희가 선택한 UI 툴키트는 wxWindgets 입니다. 작성할 필요가 있는 wxWidgets 코드는 UnrealED 안에 작성됩니다. 'Editor' 프로젝트에는 편집 툴의 모든 함수성이 들어가고, 코드는 UnrealED 에 들어간다는 개념은 그저 해당 함수성에 대한 UI 감싸개(wrapper)일 뿐입니다.

다른 플랫폼 전용 프로젝트도 여럿 있는데, D3DDrv (렌더링의 Direct 3D 구현), WinDrv (뷰포트 생성, 이벤트 처리 등의 윈도우 구현) 등입니다. 한 프로젝트가 크로스-플랫폼 인터페이스의 특정 플랫폼 전용 구현이라면 보통 Drv 같은 접미사가 붙게 마련입니다.

반응형


Licensees can log in.

Red links require licensee log in.


Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 홈 > UDK 젬 > 머티리얼 에디터 사용 안내서
UE3 홈 > 머티리얼과 텍스처 > 머티리얼 에디터 사용 안내서

머티리얼 에디터 사용 안내서


문서 변경내역: Dave Burke 작성. Daniel Wright, Richard Nalezynski, Jeff Wilson 수정. 홍성진 번역.

개요


언리얼 에디터의 머티리얼 에디터 사용법에 대한 설명서입니다. 다양한 머티리얼 표현식의 역할에 대한 설명은 Materials Compendium KR (머티리얼 개론) 페이지를, 새 머티리얼 표현식 제작법에 대해서는 Creating Material Expressions KR 페이지를 참고해 주시기 바랍니다.

모바일 플랫폼용 머티리얼 제작에 대한 정보는 Mobile Material Reference KR 페이지를 참고해 주시기 바랍니다.

머티리얼 에디터 열기


머티리얼 에디터는 머티리얼 애셋을 더블클릭하거나 콘텐츠 브라우저의 머티리얼 애셋의 우클릭 맥락 메뉴를 통해 열 수 있습니다. 어느 방법으로나 해당 머티리얼이 머티리얼 에디터에서 편집 가능한 상태로 열리게 됩니다.

머티리얼 에디터 인터페이스


머티리얼 에디터는 여섯 구역으로 구성되어 있습니다:

materialeditor.jpg

  1. 메뉴바
  2. 툴바
  3. 미리보기 패널 - 메시의 머티리얼을 미리봅니다.
  4. 머티리얼 표현식 그래프 패널 - 셰이더 인스트럭션 제작을 위해 이 패널에서 머티리얼 표현식을 결합합니다.
  5. 머티리열 표현식 패널 - 사용가능한 머티리얼 표현식 목록입니다.
  6. 머티리얼 함수 라이브러리 - 사용할 수 있는 머티리얼 함수 목록입니다.
  7. 프로퍼티 패널 - 머티리얼이나 선택된 머티리얼 표현식 노드의 프로퍼티입니다.

메뉴바

  • 프로퍼티 - 프로퍼티 패널이 표시됩니다.
  • 미리보기 - 미리보기 패널이 표시됩니다.
  • 머티리얼 표현식 - 머티리얼 표현식 그래프를 표시합니다.

툴바

toolbar.jpg

다음은 각 툴바 버튼에 대한 설명으로, 툴바 표시상 왼쪽에서 오른쪽 순입니다.

아이콘 설명
toolbar_home.jpg 메인 패널의 좌상단 코너에 베이스 머티리얼 노드가 오도록 머티리얼 표현식 그래프를 옮깁니다.
toolbar_grid.jpg 머티리얼 미리보기 패널의 배경 그리드를 토글합니다.
toolbar_cylinder.jpg toolbar_cube.jpg toolbar_sphere.jpg toolbar_plane.jpg 머티리얼 미리보기에 사용할 표준 모양을 선택합니다.
toolbar_find.jpg 콘텐츠 브라우저를 열고 머티리얼을 선택합니다.
toolbar_usestatic.jpg 콘텐츠 브라우저에서 스태틱 메시를 선택하고 이 버튼을 누르면 선택된 메시를 미리보기 메시로 지정합니다.
toolbar_clean.jpg 머티리얼에 연결되지 않은 머티리얼 표현식 노드를 지웁니다.
toolbar_show.jpg 아무것에도 연결되지 않은 머티리얼 표현식 단자를 표시/숨깁니다.
toolbar_realtime_preview.jpg 켜면 미리보기 메시의 머티리얼을 실시간으로 업데이트합니다. 에디터 성능을 위해서라면 이 옵션은 끄십시오.
toolbar_realtime_expression.jpg 켜면 각 머티리얼 표션식 노드의 머티리얼을 실시간으로 업데이트합니다. 에디터 성능을 위해서라면 이 옵션은 끄십시오.
toolbar_realtime_preview_expression.jpg 이 버튼은 머티리얼 표현식의 bRealtimePreview (실시간 미리보기) 옵션에 대한 글로벌 토글입니다. 켜면 모든 하위표현식의 셰이더는 노드가 추가, 삭제, 연결, 연결 해제, 프로퍼티 값 변경시마다 컴파일됩니다. 에디터 성능을 위해서라면 이 옵션은 끄십시오. 표현식 미리보기 부분을 참고하십시오.
toolbar_apply.jpg 머티리얼 에디터에서 변경한 사항을 원본 머티리얼과 월드에 해당 머티리얼을 사용한 곳에 적용합니다.
toolbar_stats.jpg 표현식 그래프 패널에 머티리얼 통계를 표시/숨깁니다.
toolbar_source.jpg 현재 선택된 표현식에 대한 HLSL 소스 표시를 토글합니다.
toolbar_search.jpg 텍스트 일부가 일치하는 표현식을 검색할 수 있습니다. 자세한 것은 머티리얼 표현식 검색 부분을 참고하십시오.

미리보기 패널

previewpane.jpg

머티리얼 미리보기 패널은 편집중인 머티리얼을 메시에 적용하여 보여줍니다. 마우스 왼쪽 버튼으로 끌면 메시의 회전, 가운데 버튼으로는 패닝, 오른쪽 버튼으로는 줌입니다. 라이트의 방향은 L키를 누르고 좌클릭 드래깅으로 회전시킬 수 있습니다.

관련 툴바 콘트롤(모양 버튼, "미리보기 메시 선택" 콤보 박스, "선택된 스태틱 메시 사용" 버튼 등)을 사용하여 미리보기 메시를 바꿀 수 있스니다. 미리보기 메시는 머티리얼에 저장되므로 다음 번에 머티리얼 에디터에서 열 때도 같은 메시에서 미리볼 수 있습니다.

프로퍼티 패널

propertiespane.jpg

이 패널에는 선택된 머티리얼 표현식에 대한 프로퍼티창이 담깁니다. 선택된 표현식이 없으면 편집중인 머티리얼 자체의 프로퍼티가 표시됩니다.

모든 머티리얼 프로퍼티에 대한 설명은 Materials Overview KR 페이지를 확인하시기 바랍니다.

머티리얼 표현식 패널

expressionpane.jpg

이 패널에는 "드래그 앤 드롭" 방식으로 머티리얼에 놓을 수 있는 머티리얼 표현식이 나열됩니다. 머티리얼 표현식 노드를 새로 놓으려면, 표현식에 좌클릭 > 그래프 패널로 드래그 > 원하는 위치에 드롭 하면 됩니다.

머티리얼 함수 라이브러리

functionpane.jpg

이 패널에는 "드래그 앤 드롭" 방식으로 머티리얼에 놓을 수 있는 머티리얼 함수 목록이 표시됩니다. 새로운 머티리얼 함수를 놓으려면 놓으려는 함수 종류에 왼클릭한 후, 커서를 그래프 패널 위로 끌어 놓습니다. 적합한 머티리얼 함수가 할당된 MaterialFunctionCall 노드가 새로이 놓입니다.

머티리얼 표현식 그래프 패널

graphpane.jpg

이 패널에는 이 머티리얼에 속하는 모든 머티리얼 표현식의 그래프가 포함되어 있습니다. 머티리얼에 사용된 셰이더 인스트럭션 수와 함께 컴파일러 에러 도 좌상단 구석에 표시됩니다. 인스트럭션 수가 적을 수록 머티리얼 비용도 싸집니다. 기본 머티리얼 노드에 연결되지 않은 머티리얼 표현식 노드는 머티리얼의 인스트럭션 수(비용)에 계산되지 않습니다.

머티리얼에는 디폴트로 하나의 머티리얼 노드가 포함되어 있습니다. 이 노드에는 여러가지 입력이 달려 있는데, 각각은 머티리얼의 다양한 면에 관련되어 있으며, 여기에 다른 표현식이나 표현식 망이 연결될 수 있습니다.

material_node.jpg

머티리얼 노드의 여러가지 입력에 대한 설명은 Materials Overview KR 페이지를 확인해 주시기 바랍니다.

콘트롤

머티리얼 에디터의 콘트롤은 언리얼 에디터 내의 다른 툴 콘트롤과 일반적으로는 비슷합니다. 머티리얼 표현식 그래프는 여타 오브젝트 에디터들과 같은 식으로 조작할 수 있으며, 머티리얼 미리보기 메시도 다른 메시 툴과 마찬가지로 방향을 맞출 수 있습니다.

마우스 콘트롤

콘트롤 액션
배경에 좌/우클릭-드래그 머티리얼 표현식 그래프 패닝
마우스 휠 스크롤 줌 인/아웃
좌+우클릭 드래그 줌 인/아웃
오브젝트에 좌클릭 표현식/코멘트 선택
오브젝트에 Ctrl + 좌클릭 표현식/코멘트 선택 토글
Ctrl + 좌클릭 + 드래그 현재 선택/코멘트 옮기기
Ctrl + Alt + 좌클릭 + 드래그 박스 선택
Ctrl + Alt + Shift + 드래그 박스 선택(하여 현재 선택에 추가)
단자에 좌클릭 + 드래그 (하다가 단자나 변수에서 떼면) 연결 생성
연결에 좌클릭 + 드래그 (하다가 같은 종류의 단자나 변수에서 떼면) 연결 이동
단자에 Shift + 좌클릭 단자를 마크합니다. 단자가 마킹된 상태로 다른 단자에 Shift + 클릭하면 두 단자를 연결합니다. 원거리 연결이 매우 빨라집니다.
배경에 우클릭 새 표현식 메뉴를 띄웁니다.
오브젝트에 우클릭 오브젝트 메뉴를 띄웁니다.
단자에 우클릭 오브젝트 메뉴를 띄웁니다.
단자에 Alt + 좌클릭 단자의 무든 연결을 끊습니다.
(미리보기 패널에서) L 키 + 드래그 미리보기 라이트 방향을 돌립니다.

키보드 콘트롤

콘트롤 액션
Ctrl + C 선택된 표현식 복사
Ctrl + V 붙여넣기
Ctrl + W 선택된 오브젝트 복제
Ctrl + Y 다시하기
Ctrl + Z 되돌리기
Delete 선택된 오브젝트 삭제
스페이스바 모든 머티리얼 표현식 미리보기 강제 업데이트
Enter (적용 클릭과 동일)

핫키

자주 사용되는 머티리얼 표현식 유형은 핫키로 놓을 수 있습니다. 단축키를 누르고 노드의 놓을 곳에 좌클릭하면 됩니다. 핫키는 다음과 같습니다:

핫키 표현식
A Add 더하기
B BumpOffset 범프 오프셋
C ComponentMask 컴포넌트 마스크
D Divide 나누기
E Power 파워(승)
F MaterialFunctionCall 머티리얼 함수 호출
I If 만약
L LinearInterpolate 선형 보간
M Multiply 곱하기
N Normalize 정규화
O OneMinus 1빼기
P Panner 패너
R ReflectionVector 리플렉션 벡터
S ScalarParameter 스칼라 파라미터
T TextureSample 텍스처 샘플
U TexCoord 텍스처 좌표
V VectorParameter 벡터 파라미터
1 Constant 상수
2 Constant2Vector 상수 2벡터
3 Constant3Vector 상수 3벡터
4 Constant4Vector 상수 4벡터
Shift + C Comment 코멘트

표현식 코멘트


코멘트는 머티리얼의 역할을 설명하기에 좋으며, 타인은 물론 자신에게도 복잡한 머티리얼 그래프를 이해하는 데 도움이 됩니다. 코멘트는 관련된 노드 위에 나타나는 파랑 텍스트로 표시됩니다. 코멘트는 줌과 별도로 표시되므로 복잡한 머티리얼 그래프를 쉽게 옮겨다닐 수 있습니다.

Comments.jpg

머티리얼 표현식 노드는 해당 노드의 "Desc" 프로퍼티에 텍스트를 입력하여 개별적으로 코멘트를 달 수 있습니다.

여러 노드를 선택하고 'Shift + C'를 쳐서 노드 그룹에 그룹 코멘트를 할당할 수도 있습니다. "새 코멘트" 대화창에 코멘트 텍스트를 입력하고 OK를 칩니다. 선택된 노드가 코멘트 프레임에 묶이게 됩니다. 그룹 코멘트의 노드는 그룹 코멘트 텍스트를 드래그하여 움직일 수 있습니다. 코멘트 프레임의 우하단 코너에 있는 검정 삼각형을 드래그하여 프레임 크기도 조절할 수 있습니다. 그룹 코멘트 내의 노드는 전부 프레임과 함께 움직이므로, 기존 프레임 크기를 조절하여 새 노드를 포함시킬 수도 있습니다.

코멘트를 선택하고 프로퍼티창을 통해 "Text" 프로퍼티를 변경하면 코멘트의 이름을 바꿀 수 있습니다.

표현식 미리보기


RealtimePreviewCloseup.jpg

머티리얼 에디터의 노드에는 좌상단 구석에 작은 박스가 있습니다. 이 박스는 노드의 bRealtimePreview (실시간 미리보기) 프로퍼티를 나타내며: 노랑은 켜짐, 검정은 꺼짐 입니다.

머티리얼이 어떤 식으로든 (생성, 삭제, 연결, 프로퍼티 변경 등등) 바뀔 때마다, bRealtimePreview (실시간 미리보기) 프로퍼티가 켜진 노드는 전부 그 셰이더를 다시 컴파일합니다. 머티리얼 미리보기를 해당 노드에서 최신으로 유지하려면 이런 리컴파일이 필요합니다. 그러나 이런 중간 셰이더 리컴파일은 시간을 잡아먹을 수 있는데, 특히나 머티리얼에 노드가 많을 경우에는 더합니다. 그래서 작업 방해를 피하기 위해서, TextureSample 을 제외한 모든 노드 유형에 대해서는 기본적으로 bRealtimePreview (실시간 미리보기)가 꺼져 있습니다.

스페이스바를 쳐서 강제로 모든 미리보기를 업데이트시킬 수도 있습니다. 아무튼 가급적 많은 노드의 bRealtimePreview (실시간 미리보기)를 끄고, 변경 확인시마다 스페이스를 치는 방식을 통해 반복처리 속도를 높일 수 있습니다.

노드의 좌상단 구석 박스를 클릭하거나, 노드를 선택한 상태에서 프로퍼티 창을 통해 노드의 bRealtimePreview (실시간 미리보기)를 토글할 수 있습니다.

"Toggle Expression Realtime Preview" (표현식 실시간 미리보기 토글) 버튼으로 모든 노드 글로벌 토글이 가능합니다.

컴파일러 에러


머티리얼 망에 무언가 변화가 있을 때마다 머티리얼을 컴파일해 줘야 합니다. 망 내 어느 표현식에 필요한 입력에 연결된 것이 없거나 잘못된 데이터형이 주어지는 경우, 컴파일 에러가 납니다. 이 에러는 그래프 패널 에 표시됩니다.

error_message.jpg

컴파일러 에러에 제공되는 문제 발생 표현식의 종류와 에러에 대한 설명을 통해, 그 문제가 무엇인지 알 수 있습니다. 게다가 에러가 있는 노드는 그래프 패널에 빨갛게 강조되어 보이므로, 쉽게 찾아 필요한 연결을 메꿀 수 있습니다.

error_highlight.jpg

머티리얼 표현식 검색


머티리얼 에디터의 검색 기능을 활용하면 머티리얼 망 내 (코멘트 포함) 어느 노드든, 그 설명이나 각 표현식 종류에 한정된 여러 프로퍼티에 지정한 텍스트가 포함되는 것을 빠르게 찾아 줍니다. 노드에 식별 키워드를 추가해 놓고 나중에 찾아가거나 하기가 쉬워지니, 정처없이 표현식 바다를 허우적대지 않아도 됩니다.

검색 박스에 키워드 전체나 부분을 입력하면 그래프 패널에 있는 표현식의 프로퍼티를 대상으로 검색합니다. 일치되는 것이 현재 활성 결과라면 녹색으로 강조됩니다.

search_highlight.jpg

주: 검색은 대소문자를 구별합니다.

검색 대상 프로퍼티 값은 다음과 같습니다:

표현식 종류 검색되는 프로퍼티
All Desc
Texture Sample Texture
Parameters ParamName
Comment Text
FontSample Font
MaterialFunctionCall MaterialFunction

검색에 NAME= 스위치를 사용하면 특정 표현식 종류만을 대상으로 검색할 수도 있습니다. 예를 들어 모든 텍스처 샘플러를 찾으려면:

NAME=texture

search_next_button.jpgsearch_prev_button.jpg 버튼을 사용하여 검색 결과 표현식 전부를 돌아가며 볼 수 있습니다.

search_cycle.gif

애초부터든, search_next_button.jpgsearch_prev_button.jpg 버튼으로든, 선택된 일치 결과가 보이지 않는 경우, 그래프 패널의 뷰에 나타납니다.

검색을 비우려면 search_clear_button.jpg 버튼을 누르면 됩니다.

반응형

  • 클래스 선언. 각 클래스는 하나의 부모 클래스를 "extends" (..로부터 파생) 하며, 함께 분포되는 객체들의 콜렉션인 "package" 에 속해 있습니다. 모든 함수 및 변수들은 클래스에 속하며, 그 클래스에 속해 있는 액터를 통해서만 접근할 수 있습니다. 시스템 전체의 글로벌 함수나 변수는 없습니다. 자세한 설명.

  • 변수의 선언. UnrealScript는 가장 기초적인 C/Java의 타입, 객체 참조, 구조체 그리고 배열을 포함하여 매우 다양한 변수 타입의 세트를 지원합니다. 게다가 변수들을 디자이너들이 전혀 프로그래밍 하지 않고 UnrealEd 에서 접근할 수 있는, 편집이 가능한 속성으로 변경할 수 있습니다. 이 속성들은 var 대신 var() 구문을 사용해서 지정됩니다. 자세한 설명.

  • 함수들. 함수는 매개변수의 목록을 취할 수 있으며, 선택적으로 값을 반환합니다. 함수는 로컬 변수를 가질 수 있습니다. 어떤 함수들은 Unreal 엔진 자체에 의해 호출되며 (예: BeginPlay), 어떤 함수들은 다른 곳에서 다른 스크립트 코드로부터 호출됩니다 (예:Trigger). 자세한 설명.

  • 코드. for, while, break, switch, if 등 C 와 Java 의 표준 키워드가 모두 지원됩니다. UnrealScript 에서도 괄호와 세미콜론이 C, C++ 및 Java 에서처럼 사용됩니다.

  • 액터 및 객체 참조. 함수가 객체 참조를 사용하여 다른 객체 내에서 호출되는 여러 경우를 볼 수 있습니다. 자세한 설명

  • 키워드 "state". 이 스크립트는 다수의 "state" 를 정의하고 있습니다. State 는 액터가 그 상태에 있을 때만 집행되는 함수, 변수 그리고 코드의 그룹입니다. 자세한 설명

  • UnrealScript 에서는 키워드, 변수의 이름, 함수 그리고 객체의 이름에 대소문자를 구분하지 않는다는 점에 유의하십시오. UnrealScript 에서는 Demon, demONdemon 이 모두 같은 것을 가리킵니다.

객체의 계층구조

Object 는 Unreal 내 모든 객체의 부모 클래스입니다. 모든 것들이 Object 에서 파생되기 때문에, 어디에서나 Object 클래스 내에 있는 모든 함수들에 접근할 수 있습니다. Object 는 abstract 기초 클래스이므로, 그 자체는 전혀 유용한 일을 하지 않습니다. 모든 기능성은 Texture (텍스처 맵), TextBuffer (텍스트의 덩어리), 그리고 Class (다른 객체의 클래스를 설명하는) 등의 하위클래스에 의해 제공됩니다.

Actor (extends Object) 는 Unreal 내 모든 자립형 게임 객체들의 부모 클래스입니다. Actor 클래스는 액터가 돌아다니고, 다른 액터들과 상호작용하고, 환경에 영향을 주고, 게임에 관련된 다른 유용한 일들을 하는데 필요한 모든 기능성을 함유하고 있습니다.

Pawn (extends Actor) 은 고급 수준의 AI 및 플레이어 콘트롤을 감당하는 Unreal 내 모든 창조물 및 플레이어들의 부모 클래스입니다.

Class (extends Object) 는 객체의 클래스를 설명하는 특별한 종류의 객체입니다. 클래스가 객체이고, 객체가 어떤 객체를 설명한다는 것이 처음에는 혼동스러워 보일지 모릅니다. 그러나 이 개념은 논리적인 것이며 여러분이 Class 객체를 다루어야 할 경우가 많습니다. 예를 들어 UnrealScript 에서 새 액터를 스폰할 때, 그 새 액터의 클래스를 Class 객체로 지정할 수 있습니다.

UnrealScript 를 사용해서 어떠한 Object 클래스에 대한 코드라도 작성할 수 있지만, 99% 의 경우 Actor 에서 파생된 클래스에 대한 코드를 쓰게 될 것입니다. 유용한 UnrealScript 기능성의 대부분은 게임과 관련된 것이며 액터들을 취급하는 것입니다.

클래스

각 스크립트는 정확히 하나의 클래스에 해당되며, 스크립트는 클래스, 클래스의 부모 그리고 그 클래스와 관계있는 모든 추가 정보를 선언하는 것으로 시작됩니다. 가장 간단한 클래스의 형태는 다음과 같습니다:

class MyClass extends MyParentClass;

여기서 저는 "MyParentClass" 의 기능성을 물려받는, "MyClass" 라는 이름의 새 클래스를 선언하고 있습니다. 또, 이 클래스는 "MyPackage" 라는 이름의 패키지 안에 들어 있습니다.

각 클래스는 그 부모 클래스의 변수, 함수 그리고 상태를 모두 물려 받습니다. 클래스는 그 다음에 새 변수의 선언 추가, 새 함수 추가 (또는 기존 함수 오버라이드) 그리고 새 상태를 추가 (또는 기존의 상태에 기능 추가) 할 수 있습니다.

UnrealScript 에서 클래스 디자인의 전형적인 접근방식은, 필요한 모든 기능성을 가지고 있는 기존의 클래스 (예: 괴물들의 베이스 클래스인 Pawn 클래스) 를 확장하는 새 클래스(예: Minotaur 괴물) 을 만드는 것입니다. 이 방식을 따르면 절대로 시간과 노력을 낭비할 필요가 없습니다 – 커스터마이즈 할 필요가 없는 기존의 기능을 모두 유지하면서 커스터마이즈 하고 싶은 새 기능을 간단히 추가할 수 있습니다. 이 접근방식은 Unreal 에서 AI를 구현하는데 특히 효과적입니다. 내장된 AI 시스템이 여러분 고유의 창조물에 대해 구성 요소로서 사용할 수 있는, 놀라운 양의 기본적인 기능성을 제공하기 때문입니다.

클래스 선언은 그 클래스에 영향을 미치는 다수의 선택적 지정자를 취할 수 있습니다:

Native(PackageName)
"이 클래스는 보이지 않는 곳에서 C++ 지원을 사용한다" 는 것을 나타냅니다. Unreal은 native 클래스들이 .EXE 에 C++ 구현을 포함할 것을 기대합니다. Native 클래스만이 native 함수를 선언하거나 native 인터페이스를 구현할 수 있습니다. Native 클래스들은 언제나 다른 native 클래스로부터 파생되어야 합니다. Native 클래스들은 스크립트의 변수들 및 지정한 함수들과 상호작용 하는데 필요한 glue 와 함께, 자동 생성 C++ 헤더 파일을 만들어냅니다. 기본으로, PackageName 은 해당 스크립트가 들어있는 패키지를 말합니다. 예를 들어 클래스가 Engine 패키지 내에 있다면, 결과물인 자동 생성 헤더의 이름은 EngineClasses.h 이 됩니다.
NativeReplication
이 클래스에 대한 변수 값의 복제가 C++ 구현으로 처리된다는 것을 나타냅니다. Native 클래스에서만 유효합니다.
DependsOn(ClassName[,ClassName,...])
ClassName이 이 클래스에 앞서 컴파일된다는 것을 나타냅니다. ClassName으로는 반드시 같은 패키지 (또는 이전의 패키지) 내의 클래스를 지정해야 합니다. 한 DependsOn 줄에서 콤마로 분리하거나, 각 클래스마다 별도의 DependsOn 줄을 사용하여 여러 개의 종속 클래스를 지정할 수 있습니다.
Abstract
클래스를 "abstract 기본 클래스" 로서 선언합니다. 이 클래스는 그 자체로는 아무런 의미가 없기 때문에, 사용자들이 UnrealEd 에서 이 클래스의 액터를 세계에 추가하거나, 게임을 하는 동안 이 클래스의 인스턴스를 만드는 일을 못하게 합니다. 예를 들어 기본 클래스 "Actor" 는 abstract 인 반면, 하위클래스 "Ladder" 는 abstract 이 아닙니다 — 여러분은 Ladder 를 세계에 배치할 수 있지만 Actor 를 세계에 배치할 수는 없습니다. 이 키워드는 본연의 자식 클래스에는 전파되지만 스크립트 자식 클래스에는 전파되지 않습니다.
Deprecated
이 클래스의 모든 객체들이 로드되지만 저장되지는 않게 합니다. 레벨 디자이너들이 에디터에서 맵을 로드할 때 폐기된 액터의 인스턴스가 배치되면 경고를 내보냅니다. 이 키워드는 자식 클래스들에 전파됩니다.
Transient
"이 클래스에 속하는 객체들은 절대로 디스크에 저장되면 안됨”을 말합니다. players 또는 windows 처럼 원래 지속적이지 않은 특정한 종류의 native 클래스와 함께일 때만 유용합니다. 이 키워드는 자식 클래스들에 전파됩니다; 자식 클래스들은 NotTransient 키워드를 사용하여 이 플래그를 오버라이드 할 수 있습니다.
NonTransient
기본 클래스로부터 물려받은 Transient 키워드를 무효로 합니다.
Config(IniName)
이 클래스가 .ini 에 데이터를 저장하는 것이 허용된다는 것을 가리킵니다. 클래스에 구성이 가능한
변수 ("config" 또는 "globalconfig" 와 함께 선언된)가 있으면 이 변수들이 지정한 구성 파일에 저장되도록
합니다. 이 플래그는 모든 자식 클래스에 전파되며, 무효화할 수 없습니다. 그렇지만 자식 클래스는 Config
키워드를 재선언하고 다른 IniName 을 지정함으로써 .ini 파일을 변경할 수 있습니다. 보통 IniName 은
데이터를 저장해 넣을 .ini 파일의 이름을 명기하지만, 여러가지 이름에는 다음과 같이 특별한 의미가
있습니다:
  • Config(Engine): 게임의 이름 뒤에 "Engine.ini" 가 이어지는 Engine 구성 파일을 사용합니다. 예를 들어 ExampleGame 의 엔진 구성 파일 이름은 ExampleEngine.ini가 됩니다.
  • Config(Editor): 게임의 이름 뒤에 "Editor.ini"가 이어지는 Editor 구성 파일을 사용합니다. 예를 들어 ExampleGame 의 에디터 구성 파일 이름은 ExampleEditor.ini 가 됩니다.
  • Config(Game): 게임의 이름 뒤에 "Game.ini" 가 이어지는 Game 구성 파일을 사용합니다. 예를 들어 ExampleGame 의 게임 구성 파일 이름은 ExampleGame.ini 가 됩니다.
  • Config(Input): 게임의 이름 뒤에 "Input.ini" 가 이어지는 Input 구성 파일을 사용합니다. 예를 들어 ExampleGame 의 입력 구성 파일 이름은 ExampleInput.ini 가 됩니다.
PerObjectConfig
이 클래스에 대한 구성 정보는 객체별로 저장되고, 각 객체는 [ObjectName ClassName] 의 포맷으로
객체의 이름을 따른 .ini 파일 내에 섹션을 가지고 있습니다. 이 키워드는 자식 클래스에 전파됩니다.
PerObjectLocalized
이 클래스의 현지화된 데이터는 각 객체마다 정의되며, 각 객체는 [ObjectName ClassName] 의
포맷으로 객체의 이름을 따른 현지화 파일 내에 섹션을 가지고 있습니다. 이 키워드는 자식 클래스에
전파됩니다.
EditInlineNew
에디터. 이 클래스의 객체들이 UnrealEd 속성 창으로부터 작성될 수 있음을 나타냅니다 (기존의 객체에
대한 참조만이 속성창을 통해 배정되는 것이 기본 행태입니다). 이 플래그는 모든 자식 클래스에
전파됩니다; 자식 클래스는 NotEditInlineNew 키워드를 사용하여 이 플래그를 오버라이드 할 수
있습니다.
NotEditInlineNew
에디터. 기본 클래스로부터 물려받은 EditInlineNew 키워드를 무효로 합니다. EditInlineNew 를 사용하는 부모 클래스가 없는 경우에는 효과가 없습니다.
Placeable
에디터. 이 클래스가 UnrealEd 에서 작성되어 레벨, UI 의 장면, 또는 키스멧 창에 배치될 수 있다는 것
나타냅니다 (클래스의 타입에 따라). 이 플래그는 모든 자식 클래스에 전파됩니다;
자식 클래스는 NotPlaceable 키워드를 사용하여 이 플래그를 오버라이드 할 수 있습니다.
NotPlaceable
에디터. 기본 클래스로부터 물려받은 Placeable 키워드를 무효로 합니다. 이 클래스가 UnrealEd 에서
레벨 등에 배치될 수 없음을 나타냅니다.
HideDropDown
에디터. 이 클래스가 UnrealEd 속성 창의 콤보 박스에 나타나지 못하도록 합니다.
HideCategories(Category[,Category,...])
에디터. 이 클래스의 객체들에 대해 UnrealEd 의 속성 창에서 숨겨져야 할 하나 또는 그 이상의
카테고리를 명시합니다.
카테고리가 없이 선언된 변수들을 숨기려면, 그 변수를 선언한 클래스의 이름을 사용합니다.
ShowCategories(Category[,Category,...])
에디터. 기본 클래스로부터 물려받은 HideCategories 키워드를 무효로 합니다.
AutoExpandCategories(Category[,Category,...])
에디터. 이 클래스의 객체들에 대해 UnrealEd 의 속성 창에서 자동으로 확장되어야 할 하나 또는
그 이상의 카테고리를 명시합니다.
카테고리가 없이 선언된 변수들을 자동 확장하려면, 그 변수를 선언한 클래스의 이름을 사용합니다.
Collapsecategories
에디터. 이 클래스의 속성들이 UnrealEd 의 속성 창에서 카테고리로 그룹지어져서는 안된다는 나타냅니다.
이 키워드는 자식 클래스에 전파됩니다; 자식 클래스는 DontCollapseCategories 키워드를 사용하여
이 플래그를 오버라이드 할 수 있습니다.
DontCollapseCategories
에디터. 기본 클래스로부터 물려받은 CollapseCatogories 키워드를 무효로 합니다.
Within ClassName
고급. 이 클래스의 객체들은 ClassName의 인스턴스 없이는 존재할 수 없다는 것을 나타냅니다.
이 클래스의 객체를 만들려면 반드시 ClassName의 인스턴스를 Outer 객체로서 지정해야 합니다.
이 키워드는 반드시 클래스 자체의 선언 뒤에 첫번째로 와야 합니다.
Inherits(ClassName[,ClassName,...])
고급. 복수의 상속에 대해 사용되며 추가의 기본 클래스를 지정합니다.Inherits 줄에서 콤마로
분리하거나, 각 기본 클래스마다 별도의 nherits 줄을 사용하여 복수의 기본 클래스를 지정할
수 있습니다. Native 클래스에 대해서만 유효합니다. UObject 에서 파생된 두 개의 클래스로부터의
복수 상속은 지원되지 않습니다.
Implements(ClassName[,ClassName,...])
고급. 이 클래스에서 구현할 하나 또는 그 이상의 인터페이스 클래스를 명시합니다.
Implements 줄에서 콤마로 분리하거나, 각 인터페이스 클래스마다 별도의 Implements 줄을 사용하여
복수의 인터페이스 클래스를 지정할 수 있습니다. Native 클래스만이 native 인터페이스를 구현할 수 있습니
다.
NoExport
고급. 이 클래스의 C++ 선언이 스크립트 컴파일러에 의해 자동생성된 C++ 헤더 파일에 포함되면 안된다는
것을 나타냅니다. C++ 클래스 선언은 반드시 별도의 헤더 파일에 수동으로 정의되어야 합니다. native
클래스에 대해서만 유효합니다.  

반응형

udk.exe 설정시 win32/UDK.exe 로 설정

DefaultEngine.ini

ModEditPackages=MyMod 를

ModEditPackages=MyGame 로 변경

.uc 페이지 유니코드 949 로 변경

프로젝트 만들때 솔루션용 디렉터리 만들기 체크 해제

http://blog.naver.com/kiru81?Redirect=Log&logNo=60106380729

nFringe 라는 프로그램을 다운받는디.

http://wiki.pixelminegames.com/index.php?title=Tools:nFringe#First_time_installation

nFringe 를 설치한 후, VC++ 2005 나 2008 을 실행하고 새 프로젝트를 만들게 되면, 프로젝트 형식에 UnrealScript 라는 항목을 볼 수 있다.

VC++ 2005 에서 할 경우에는 한 가지를 더 설치해주어야 한다. 바로 ProjectAggregator2 이다. 위의 링크된 위키사이트에서 다운받을 수 있다. VC++ 2008 로는 테스트해보지 않았지만, 아마 필요없는 것 같다.

프로그램 셋팅 및 코드 작성은 아래 동영상을 참고

http://dl.deathtouchstudios.com/videotutorials/UnrealScriptSeries/

1. UnrealEngine 3 License Project 템플릿으로 프로젝트 생성

2. 프로젝트 속성 > General 탭에 Game > Target Game 을 UnrealEngine 3 Mod 로 바꿈.

Script Compiler > UCC Path 를 Binaries\UDK.exe 로 설정

Script Compiler > Reference Source Path 를 Development\Src 로 설정

3. Build 탭에 Script Outputs > Manually set UCC output directory 를 체크하고 UDKGame\Script 를 경로로 잡아준다.

4. Debug 탭에 StartAction

프로젝트 셋팅 시 Debug 탭에서 Load map at startup 이라는 항목이 있는데, 여기에는 자신이 만들어 저장한 맵의 이름을 저장해야 한다.

아래는 test.udk 로 3인칭 시점의 카메라를 테스트 했던 맵을 지정하고, 실행한 결과이다.

근데 로그를 출력해보는 중에 warning 이 발생.. MyGame.MyGameInfo 를 찾지 못한다는 거였다..

\UDK\UDK-2010-04\UDKGame\Script 에 MyGame.u 파일이 생성되지 않는 것과 관계가 있는걸까?

반응형

+ Recent posts