Cocos 미니게임 캐릭터 이동과 공격: 노드에서 애니메이션까지 구현하기

캐릭터가 화면 중앙에 서 있습니다. 방향키를 눌렀는데 아무 움직임이 없습니다. 코드를 열어 보니 이동 로직, 애니메이션 재생, 상태 판단이 모두 하나의 update 함수 안에 쌓여 있습니다. 애니메이션을 고치다 상태를 빠뜨리고, 상태를 고치다 속도를 놓치고, 결국 지금 캐릭터가 무엇을 해야 하는지 만든 사람도 헷갈리게 됩니다.
노드 분리라는 말은 조금 추상적으로 들리지만, 쉽게 말하면 이동과 애니메이션을 나눠서 관리한다는 뜻입니다. Player 노드는 수평 이동을 담당하고, Body 노드는 수직 점프와 공격 애니메이션을 처리합니다. 두 흐름은 독립적으로 동작하므로 서로 간섭하지 않습니다. 이 글에서는 노드 구조부터 시작해 애니메이션 컴포넌트 설정, 상태 머신 구현, 입력 제어 방식 선택까지 차례로 다루고, 마지막에는 완성된 횡스크롤 격투 캐릭터 코드를 제공합니다.
캐릭터 노드 구조 설계: 수평 이동과 수직 애니메이션 중첩
Cocos Creator 3.7 공식 튜토리얼에는 쉽게 지나치기 쉬운 설계가 있습니다. Player와 Body 두 노드를 분리하는 방식입니다. 많은 사람은, 저 역시 처음에는, 굳이 그럴 필요가 있나 싶어 합니다. 하나의 노드에서 이동, 애니메이션, 충돌 감지를 모두 관리해도 단순해 보이기 때문입니다.
문제는 애니메이션과 이동의 리듬이 서로 다르다는 데서 시작됩니다. 캐릭터가 점프하는 장면을 떠올려 보세요. 수평 방향으로는 일정한 속도로 앞으로 날아가지만, 수직 방향으로는 포물선을 그립니다. 단일 노드를 쓰면 update 안에서 수평 이동도 계산하고 점프 높이도 제어해야 하므로 코드가 점점 흐트러집니다. 여기에 공격 애니메이션, 피격 효과, 사망 시 회전과 스케일까지 추가되면 단일 노드의 로직은 거의 통제하기 어려워집니다.
노드 분리의 장점은 명확합니다. 이동은 이동대로, 애니메이션은 애니메이션대로 관리합니다. Player 노드는 x 좌표의 증감만 담당하고, Body 노드는 y 좌표의 점프와 애니메이션 프레임 전환만 담당합니다. 서로의 역할을 빼앗지 않습니다.
노드 구조 예시:
Player(루트 노드)
├── PlayerControl.ts(이동 로직)
└── Body(자식 노드)
├── Sprite(캐릭터 이미지)
└── Animation 컴포넌트
코드 예제: Player 노드 이동 제어:
// PlayerControl.ts - Player 노드 스크립트
@property(CCFloat)
speed: number = 200; // 이동 속도
private moveDir: Vec2 = new Vec2(0, 0);
update(dt: number) {
if (this.moveDir.mag() > 0.5) {
const vx = this.moveDir.x * this.speed;
this.node.x += vx * dt; // 수평 위치만 변경
}
}
// 외부에서 방향 설정
setMoveDir(dir: Vec2) {
this.moveDir = dir;
}
코드 예제: Body 노드 애니메이션 제어:
// BodyControl.ts - Body 노드 스크립트
@property(Animation)
animation: Animation = null;
jump(height: number = 100) {
// 점프 애니메이션: 수직 이동 + jump 애니메이션 프레임
this.node.runAction(cc.jumpBy(1.0, 0, 0, height, 1));
this.animation.play('jump');
}
attack() {
this.animation.play('attack');
// 공격 종료 후 idle로 자동 복귀
this.scheduleOnce(() => {
this.animation.play('idle');
}, 0.5);
}
이렇게 나누면 이동 로직은 Player 노드에, 애니메이션 로직은 Body 노드에 위치합니다. 점프 높이를 바꿀 때 이동 코드를 건드릴 필요가 없고, 이동 속도를 바꿀 때 애니메이션 스크립트를 뒤질 필요도 없습니다. 코드 유지보수가 훨씬 편해집니다.
애니메이션 컴포넌트 설정: Animation과 AnimationClip 연결
Animation 컴포넌트는 Cocos Creator의 내장 모듈입니다. 하지만 몇 가지 핵심 속성은 놓치기 쉽습니다. defaultClip, clips 배열, 그리고 자주 간과되는 playOnLoad입니다.
Animation 컴포넌트의 핵심 속성:
defaultClip: 기본으로 재생할 애니메이션입니다. 보통 대기 애니메이션을 사용합니다.clips: 대기, 걷기, 공격 같은 AnimationClip 리소스 배열입니다.currentClip: 현재 재생 중인 애니메이션입니다. 런타임 상태를 나타냅니다.
설정 절차는 단순합니다.
- Body 노드에 Animation 컴포넌트를 추가합니다.
- AnimationClip 리소스를 clips 배열에 끌어 넣습니다.
- defaultClip을 대기 애니메이션으로 설정합니다.
- playOnLoad를 체크해 캐릭터가 시작부터 대기 상태로 서 있게 합니다.
코드 예제: 애니메이션 컴포넌트 설정:
// PlayerAnimation.ts - 애니메이션 제어 스크립트
@property(Animation)
animation: Animation = null;
@property([AnimationClip])
clips: AnimationClip[] = []; // 대기, 걷기, 공격, 점프
onLoad() {
this.animation.clips = this.clips;
this.animation.defaultClip = this.clips[0]; // 기본 대기
this.animation.play();
}
playIdle() { this.animation.play('idle'); }
playMove() { this.animation.play('move'); }
playAttack() {
this.animation.play('attack');
this.scheduleOnce(() => { this.playIdle(); }, 0.5);
}
한 가지 세부 사항이 있습니다. 애니메이션을 전환할 때는 먼저 stop()을 호출한 뒤 play()하는 편이 좋습니다. 특히 공격 애니메이션처럼 한 번만 재생되는 클립에서는 더 중요합니다. 이렇게 하지 않으면 캐릭터가 걷는 중 공격 키를 눌렀을 때 공격 애니메이션과 걷기 애니메이션이 프레임을 두고 충돌할 수 있습니다. 화면에서는 캐릭터가 칼을 휘두르면서 미끄러지는 것처럼 보여 꽤 어색합니다.
올바른 애니메이션 전환 방식:
switchAnimation(name: string) {
if (this.animation.currentClip?.name !== name) {
this.animation.stop();
this.animation.play(name);
}
}
애니메이션 컴포넌트를 설정했다면 다음 단계는 상태 머신입니다. 애니메이션 전환을 여기저기 흩어진 if (속도>0) play('move') 같은 판단에 맡기지 않고 규칙 있게 관리하기 위해서입니다.
애니메이션 상태 머신 구동: 대기, 이동, 공격, 다시 대기
상태 머신의 핵심 생각은 단순합니다. 캐릭터는 어느 순간에든 하나의 상태, 예를 들어 idle, move, attack 중 하나에만 있어야 합니다. 그리고 상태 사이에는 명확한 전환 조건이 있어야 합니다. 아무 때나 바꾸는 것이 아니라 규칙에 따라 전환합니다.
저도 처음에는 상태 머신이 조금 과한 설계라고 생각했습니다. 어차피 애니메이션을 재생하는 일이라면 그냥 play('attack')을 호출하면 되지 않을까 싶었습니다. 하지만 점프 상태를 추가하고, 다시 피격 상태까지 넣고 나니 상태 전환 판단이 곳곳에 흩어졌습니다. 이동 스크립트에도 판단이 있고, 애니메이션 스크립트에도 판단이 있고, 입력 처리에도 판단이 있었습니다. 한 곳의 판단 로직을 고쳤는데 나머지 두 곳을 함께 수정하지 않으면 캐릭터 동작에 버그가 생기기 시작했습니다.
상태 머신 흐름도:
[Entry] → [idle]
↓ speed>0
[move]
↓ attackKey
[attack] → [Exit] → [idle]
세 가지 상태는 idle(대기), move(이동), attack(공격)입니다. 전환 조건은 다음과 같습니다.
- idle → move: 속도가 0보다 큼
- move → idle: 속도가 0
- any → attack: 공격 키를 누름
- attack → idle: 공격 애니메이션 종료
코드 예제: 상태 머신 구현:
// PlayerStateMachine.ts
enum State {
Idle = 'idle',
Move = 'move',
Attack = 'attack'
}
@property(Animation)
animation: Animation = null;
private currentState: State = State.Idle;
private isMoving: boolean = false;
private attackKeyPressed: boolean = false;
switchState(newState: State) {
if (this.currentState === newState) return; // 중복 방지
this.animation.stop();
this.animation.play(newState);
this.currentState = newState;
}
update(dt: number) {
// 이동 상태 판단
if (this.isMoving && this.currentState !== State.Move) {
this.switchState(State.Move);
} else if (!this.isMoving && this.currentState !== State.Idle) {
this.switchState(State.Idle);
}
// 공격 상태: 이동보다 우선순위가 높음
if (this.attackKeyPressed && this.currentState !== State.Attack) {
this.switchState(State.Attack);
this.scheduleOnce(() => { this.switchState(State.Idle); }, 0.5);
}
}
setMoving(value: boolean) { this.isMoving = value; }
triggerAttack() {
this.attackKeyPressed = true;
this.scheduleOnce(() => { this.attackKeyPressed = false; }, 0.1);
}
상태 머신에서 중요한 세부 사항은 세 가지입니다.
- 상태 우선순위: 공격은 이동보다 우선합니다. 공격 중에는 이동하면 안 됩니다.
- 중복 전환 방지:
if (currentState === newState) return으로 같은 상태가 반복 재생되는 일을 막습니다. - 타이머 콜백: 공격 애니메이션이 끝난 뒤 키를 뗄 때까지 기다리지 않고 idle로 자동 복귀합니다.
상태 머신은 애니메이션 전환 로직을 한곳으로 모아 줍니다. 전환 조건을 수정할 때도 한 곳만 바꾸면 됩니다. 나중에 점프, 피격, 사망 상태를 추가하더라도 State 열거형에 값을 추가하고 전환 조건을 보강하면 됩니다. 흩어진 if 판단보다 확장성이 훨씬 좋습니다.
입력 제어 방식 비교: 키보드 vs 터치 vs 가상 조이스틱
세 가지 방식은 각각 어울리는 장면이 다릅니다. 잘못 고르면 조작감이 크게 떨어집니다.
| 방식 | 적합한 장면 | 장점 | 단점 | 구현 난이도 |
|---|---|---|---|---|
| 키보드 | PC, 디버깅 단계 | 단순하고 직접적이며 반응이 빠름 | 모바일에서 사용할 수 없음 | 낮음 |
| 터치 | 전체 화면 이동 게임(비행, 러닝) | 조작이 자연스럽고 UI가 가리지 않음 | 방향 정확도가 낮고 오작동이 쉬움 | 중간 |
| 가상 조이스틱 | ARPG, 격투 게임 | 방향이 정확하고 360도 제어 가능 | UI가 화면 공간을 차지함 | 높음 |
키보드 입력(PC 우선)
미니게임이 주로 PC에서 실행되거나 디버깅 단계에서 로직을 빠르게 검증해야 한다면 키보드가 가장 단순한 방식입니다.
코드 예제: 키보드 입력:
// KeyboardInput.ts
private moveDir: Vec2 = new Vec2(0, 0);
onLoad() {
input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
input.on(Input.EventType.KEY_UP, this.onKeyUp, this);
}
onKeyDown(event: EventKeyboard) {
switch (event.keyCode) {
case KeyCode.KEY_A:
case KeyCode.ARROW_LEFT:
this.moveDir.x = -1; break;
case KeyCode.KEY_D:
case KeyCode.ARROW_RIGHT:
this.moveDir.x = 1; break;
case KeyCode.KEY_J:
this.playerStateMachine.triggerAttack(); break;
}
}
onKeyUp(event: EventKeyboard) {
switch (event.keyCode) {
case KeyCode.KEY_A:
case KeyCode.ARROW_LEFT:
case KeyCode.KEY_D:
case KeyCode.ARROW_RIGHT:
this.moveDir.x = 0; break;
}
}
update(dt: number) {
this.playerControl.setMoveDir(this.moveDir);
this.playerStateMachine.setMoving(this.moveDir.mag() > 0.5);
}
키보드 입력에서 볼 세부 사항은 다음과 같습니다.
- 키 매핑: A/D와 좌우 화살표를 모두 지원해 플레이어 습관에 맞춥니다.
- 공격 키: 격투 게임에서 자주 쓰는 J 키를 사용합니다.
- 상태 동기화: 매 프레임 이동 방향과 상태 머신을 갱신합니다.
가상 조이스틱(모바일 우선)
미니게임이 모바일에서 실행되고, 횡스크롤 격투나 ARPG처럼 정확한 방향 제어가 필요한 게임이라면 가상 조이스틱은 거의 필수 선택입니다.
가상 조이스틱 구현의 핵심은 다음과 같습니다.
- 경계 제한: 조이스틱 핸들이 배경 원의 범위를 벗어나면 안 됩니다.
- 방향 정규화: 단위 벡터를 반환해야 합니다.
- 터치 해제: 손을 떼면 조이스틱이 자동으로 중심으로 돌아와야 합니다.
코드 예제: 가상 조이스틱 구현:
// Joystick.ts
@property(Node)
joystickBg: Node = null;
@property(Node)
joystickHandle: Node = null;
@property(CCFloat)
radius: number = 100;
private moveDir: Vec2 = new Vec2(0, 0);
onLoad() {
input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
}
onTouchMove(event: EventTouch) {
const touchPos = event.getUILocation();
const localPos = this.joystickBg.inverseTransformPoint(
v3(), v3(touchPos.x, touchPos.y, 0)
);
const distance = localPos.length();
if (distance > this.radius) {
localPos.x = this.radius * localPos.x / distance;
localPos.y = this.radius * localPos.y / distance;
}
this.joystickHandle.setPosition(localPos);
this.moveDir = v2(localPos.x, localPos.y).normalize();
}
onTouchEnd() {
this.joystickHandle.setPosition(Vec3.ZERO);
this.moveDir = v2(0, 0);
}
getMoveDir(): Vec2 { return this.moveDir; }
가상 조이스틱에서 중요한 세부 사항은 다음과 같습니다.
- 좌표 변환:
inverseTransformPoint로 화면 좌표를 노드 로컬 좌표로 바꿉니다. - 반지름 제한:
if (distance > radius)로 조이스틱이 배경 원을 벗어나지 않게 합니다. - 정규화:
normalize()가 단위 벡터를 반환하므로 이동 스크립트에서 속도와 바로 곱하기 쉽습니다.
비행 게임이나 러닝 게임처럼 정확한 방향 제어가 필요하지 않은 경우에는 전체 화면 터치를 사용할 수도 있습니다. 화면 어디에서든 손가락을 움직여 캐릭터를 제어하는 방식입니다. 다만 이런 게임의 입력 로직은 가상 조이스틱과 다르므로 게임 유형에 맞춰 조정해야 합니다.
실전 사례: 횡스크롤 격투 캐릭터 제어 완성 구현
앞에서 다룬 노드 구조, 애니메이션 설정, 상태 머신, 입력 제어를 하나의 완성된 횡스크롤 격투 캐릭터 제어 방식으로 통합해 보겠습니다.
완성 코드 구조:
Player(루트 노드)
├── PlayerControl.ts(이동 제어)
├── PlayerStateMachine.ts(상태 머신)
└── KeyboardInput.ts(키보드 입력)
Body(자식 노드)
├── Sprite(캐릭터 이미지)
├── Animation 컴포넌트
└── AttackEffect(공격 효과 노드, 선택 사항)
완성 코드 예제: PlayerControl.ts:
import { _decorator, Component, Node, Vec2, CCFloat } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('PlayerControl')
export class PlayerControl extends Component {
@property(CCFloat)
speed: number = 200;
private moveDir: Vec2 = new Vec2(0, 0);
update(dt: number) {
if (this.moveDir.mag() > 0.5) {
const vx = this.moveDir.x * this.speed;
this.node.x += vx * dt;
}
}
setMoveDir(dir: Vec2) { this.moveDir = dir; }
}
완성 코드 예제: PlayerStateMachine.ts:
import { _decorator, Component, Animation } from 'cc';
const { ccclass, property } = _decorator;
enum State {
Idle = 'idle',
Move = 'move',
Attack = 'attack'
}
@ccclass('PlayerStateMachine')
export class PlayerStateMachine extends Component {
@property(Animation)
animation: Animation = null;
private currentState: State = State.Idle;
private isMoving: boolean = false;
private attackKeyPressed: boolean = false;
onLoad() { this.animation.play('idle'); }
switchState(newState: State) {
if (this.currentState === newState) return;
this.animation.stop();
this.animation.play(newState);
this.currentState = newState;
}
update(dt: number) {
if (this.isMoving && this.currentState !== State.Move) {
this.switchState(State.Move);
} else if (!this.isMoving && this.currentState !== State.Idle) {
this.switchState(State.Idle);
}
if (this.attackKeyPressed && this.currentState !== State.Attack) {
this.switchState(State.Attack);
this.scheduleOnce(() => { this.switchState(State.Idle); }, 0.5);
}
}
setMoving(value: boolean) { this.isMoving = value; }
triggerAttack() {
this.attackKeyPressed = true;
this.scheduleOnce(() => { this.attackKeyPressed = false; }, 0.1);
}
}
완성 코드 예제: KeyboardInput.ts:
import { _decorator, Component, input, Input, EventKeyboard, KeyCode, Vec2 } from 'cc';
import { PlayerControl } from './PlayerControl';
import { PlayerStateMachine } from './PlayerStateMachine';
const { ccclass, property } = _decorator;
@ccclass('KeyboardInput')
export class KeyboardInput extends Component {
@property(PlayerControl)
playerControl: PlayerControl = null;
@property(PlayerStateMachine)
stateMachine: PlayerStateMachine = null;
private moveDir: Vec2 = new Vec2(0, 0);
onLoad() {
input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
input.on(Input.EventType.KEY_UP, this.onKeyUp, this);
}
onDestroy() {
input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
input.off(Input.EventType.KEY_UP, this.onKeyUp, this);
}
onKeyDown(event: EventKeyboard) {
switch (event.keyCode) {
case KeyCode.KEY_A:
case KeyCode.ARROW_LEFT:
this.moveDir.x = -1; break;
case KeyCode.KEY_D:
case KeyCode.ARROW_RIGHT:
this.moveDir.x = 1; break;
case KeyCode.KEY_J:
this.stateMachine.triggerAttack(); break;
}
}
onKeyUp(event: EventKeyboard) {
switch (event.keyCode) {
case KeyCode.KEY_A:
case KeyCode.ARROW_LEFT:
case KeyCode.KEY_D:
case KeyCode.ARROW_RIGHT:
this.moveDir.x = 0; break;
}
}
update(dt: number) {
this.playerControl.setMoveDir(this.moveDir);
this.stateMachine.setMoving(this.moveDir.mag() > 0.5);
}
}
실행 결과:
- 게임 시작 → 캐릭터 대기 애니메이션 재생
- A/D 또는 좌우 화살표 누름 → 캐릭터 이동 + 걷기 애니메이션
- J 키 누름 → 캐릭터 공격 + 공격 애니메이션 → 0.5초 뒤 대기 상태 복귀
- 방향키 해제 → 캐릭터 이동 정지 + 대기 애니메이션
흔한 문제와 해결 방법:
- 애니메이션 전환 끊김: AnimationClip의 프레임률이 너무 낮지 않은지 확인합니다. 12-24fps를 권장합니다.
- 상태 잔류: 공격 애니메이션 종료 후 idle로 돌아오지 않는다면 타이머 콜백이 정상 실행되는지 확인합니다.
- 입력 충돌: 공격 중 캐릭터가 계속 움직인다면 상태 머신에서 공격 상태의 우선순위를 이동 판단보다 높게 두었는지 확인합니다.
코드를 통합하고 나면 캐릭터 제어 로직은 명확해집니다. 이동은 PlayerControl, 애니메이션은 StateMachine, 입력은 KeyboardInput이 맡습니다. 세 스크립트는 인터페이스로 통신하며 서로 간섭하지 않습니다.
정리
핵심 구조는 세 단계입니다.
- 노드 분리: Player는 이동을, Body는 애니메이션을 담당하며 서로의 역할을 침범하지 않습니다.
- 상태 머신: idle, move, attack 세 가지 상태와 명확한 전환 조건을 한곳에서 관리합니다.
- 입력 제어: PC에서는 키보드, 모바일에서는 가상 조이스틱을 사용하며 게임 유형에 맞춰 선택합니다.
이 세 단계 구조의 장점은 한 곳을 바꿔도 다른 곳에 영향이 적다는 점입니다. 이동 속도를 빠르게 해도 애니메이션 로직을 고칠 필요가 없습니다. 공격 애니메이션에 효과를 추가해도 이동 스크립트를 수정할 필요가 없습니다. 입력 방식을 가상 조이스틱으로 바꿔도 상태 머신 로직은 그대로 둘 수 있습니다.
다음 단계에서는 이 시리즈 4편인 “미니게임 상태 머신 설계”의 3단 중첩 구조를 결합해 캐릭터에 더 복잡한 상태 관리를 추가할 수 있습니다. 예를 들면 점프, 피격, 사망, 스킬 발동 같은 상태입니다. 캐릭터 상태 머신은 게임 상태 머신의 하위 모듈일 뿐입니다. 확장 방식도 같습니다. 상태를 정의하고, 전환 조건을 설정하고, 전환 로직을 한곳에서 관리하면 됩니다.
Cocos Creator 캐릭터 이동과 공격 구현 절차
노드 구조 설계부터 입력 제어까지, 횡스크롤 격투 캐릭터 제어를 완성합니다.
⏱️ Estimated time: 45 min
- 1
Step 1: 노드 구조 설계
Player 루트 노드를 만들고 이동 제어 스크립트를 붙입니다. Body 자식 노드에는 Animation 컴포넌트와 Sprite를 둡니다. Player는 x 좌표 증감만 제어하고, Body는 y 좌표 점프와 애니메이션 프레임 전환을 처리합니다. - 2
Step 2: 애니메이션 컴포넌트 설정
Body 노드에 Animation 컴포넌트를 추가하고, 대기, 걷기, 공격 등의 AnimationClip 리소스를 넣습니다. defaultClip은 대기 애니메이션으로 설정하고 playOnLoad를 켭니다. 코드에서는 animation.play('clipName')으로 애니메이션을 전환합니다. - 3
Step 3: 상태 머신 구현
State 열거형(Idle, Move, Attack)을 정의하고 switchState 메서드를 구현합니다. update에서 isMoving과 attackKeyPressed에 따라 상태를 전환합니다. 공격 상태는 scheduleOnce 타이머로 0.5초 뒤 idle로 돌아가게 합니다. - 4
Step 4: 입력 제어 연결
KeyboardInput 스크립트를 만들어 KEY_DOWN과 KEY_UP 이벤트를 수신합니다. A/D와 좌우 화살표는 이동 방향을 제어하고, J 키는 공격을 트리거합니다. update에서는 매 프레임 moveDir을 PlayerControl과 StateMachine에 동기화합니다. - 5
Step 5: 테스트와 조정
게임을 실행해 대기 애니메이션이 정상 재생되는지, 방향키를 누르면 캐릭터가 이동하며 걷기 애니메이션으로 바뀌는지, 공격 키를 누르면 공격 애니메이션 뒤 자동으로 대기 상태로 돌아오는지 확인합니다.
FAQ
왜 Player와 Body를 두 노드로 나누어야 하나요?
애니메이션 전환 중 캐릭터가 칼을 휘두르면서 미끄러지듯 이동합니다. 어떻게 해결하나요?
공격 애니메이션이 끝난 뒤에도 공격 프레임에 머물고 대기 애니메이션으로 돌아오지 않습니다.
PC와 모바일에서는 어떤 입력 방식을 선택해야 하나요?
가상 조이스틱의 경계 제한과 정규화는 어떻게 구현하나요?
상태 머신의 공격 상태는 왜 키를 뗄 때가 아니라 타이머로 idle에 돌아가야 하나요?
5분 읽기 · 게시일: 2026년 5월 21일 · 수정일: 2026년 10월 21일
AI 기반 Cocos 미니게임 개발
검색으로 들어왔다면 같은 시리즈의 이전 글이나 다음 글로 이동하는 것이 가장 빠릅니다.
이전
미니게임 UI 리소스 네이밍 규칙: 투명 이미지, 버튼, 아이콘, 캐릭터 소재
미니게임 UI 리소스 네이밍 규칙을 익혀 보세요. 버튼 상태, 아이콘 분류, 캐릭터 애니메이션 프레임까지 아우르는 완전한 이름 공식과 Tencent 게임 팀의 7가지 황금 원칙으로 프로젝트 파일을 한눈에 파악하고 팀 협업 효율을 80% 높일 수 있습니다.
21편 중 9편
다음
미니게임의 손맛은 어디서 오는가: 플래시, 진동, 플로팅 텍스트, 사운드, 파티클 피드백
게임 손맛 설계 실전 가이드: 19가지 특성 프레임워크부터 구체적인 파라미터까지, 50-100ms 플래시, 0.08초 40Hz 진동, 플로팅 텍스트와 사운드 12ms 동기화 구현 방안을 Cocos Creator와 Unity 코드 예제로 설명합니다
21편 중 11편



댓글
GitHub로 로그인하여 댓글을 남기세요