# Camera

Como criador, você pode ter controle total sobre a câmera do jogador. Por padrão, os jogadores podem escolher entre o modo de câmera em 1ª ou 3ª pessoa enquanto exploram sua cena, mas você pode impor uma modalidade de câmera diferente.

Câmeras virtuais podem ser estáticas, podem girar para sempre olhar para o jogador ou alguma outra entidade, ou podem ser anexadas ao jogador ou outra entidade para que sempre os acompanhem.

{% hint style="warning" %}
**📔 Nota**: Para alternar entre as câmeras padrão de 1ª e 3ª pessoa, veja [Áreas modificadoras de câmera](#1st-and-3rd-person-camera-modes).
{% endhint %}

## Modos de câmera em 1ª e 3ª pessoa

Normalmente os jogadores podem alternar entre a câmera em primeira e terceira pessoa pressionando V no teclado. Use um `CameraModeArea` para forçar o modo de câmera para 1ª ou 3ª pessoa para todos os jogadores que estiverem dentro de uma área específica em sua cena.

```ts
const entity = engine.addEntity()

CameraModeArea.create(entity, {
	area: Vector3.create(4, 3, 4),
	mode: CameraType.CT_FIRST_PERSON,
})
```

Se o modo de câmera atual do jogador não corresponder ao do `CameraModeArea`, ele fará a transição para esse modo de câmera. Um toast aparece na tela para esclarecer que essa mudança se deve à cena. Enquanto estiver dentro, os jogadores não podem alterar seu modo de câmera. Quando um jogador sai da `CameraModeArea`, seu modo de câmera é restaurado para o que tinha antes de entrar.

Use `CameraModeArea` em regiões onde os jogadores teriam uma experiência significativamente melhor usando um modo de câmera específico. Por exemplo, a primeira pessoa é ideal se o jogador precisa clicar em objetos pequenos, ou a terceira pessoa pode ser útil para os jogadores notarem alguma entidade que sua cena tenha anexado acima de suas cabeças. Não presuma que os jogadores sabem como alternar modos de câmera; muitos jogadores de primeira viagem podem não saber que têm a opção ou não lembrar a tecla para fazê-lo.

{% hint style="warning" %}
**📔 Nota**: Áreas modificadoras de câmera são afetadas pelo *position* e *rotation* do componente Transform da entidade hospedeira, mas não são afetadas pela *scale*.
{% endhint %}

{% hint style="warning" %}
**📔 Nota**: Se você sobrepor múltiplas áreas modificadoras de câmera, a última instanciada pelo código da sua cena terá prioridade sobre as outras.
{% endhint %}

Ao criar um `CameraModeArea` componente, você deve fornecer o seguinte:

* `area`: Tamanho da área do modificador
* `cameraMode`: Qual modo de câmera forçar nesta área, a partir do `CameraType` enum.

Os modos de câmera suportados são:

* `CameraType.CT_FIRST_PERSON`
* `CameraType.CT_THIRD_PERSON`

### Consultar o modo de câmera

Você pode consultar o modo de câmera do jogador usando o `CameraMode` componente no `engine.CameraEntity`.

```ts
const cameraMode = CameraMode.get(engine.CameraEntity)
if (cameraMode.mode === CameraType.CT_FIRST_PERSON) {
	console.log('O jogador está usando a câmera em 1ª pessoa')
} else {
	console.log('O jogador está usando a câmera em 3ª pessoa')
}
```

Você também pode se inscrever para mudanças no modo de câmera usando o `onChange` função no `CameraMode` componente.

```ts
CameraMode.onChange(engine.CameraEntity, (cameraMode) => {
	if (!cameraMode) return
	console.log('O modo de câmera do jogador mudou para', cameraMode.mode)
})
```

## Usando câmeras virtuais

Para usar um comportamento de câmera personalizado em sua cena, você precisa de duas coisas:

* Criar uma Câmera Virtual: Crie uma entidade em sua cena e atribua-lhe um `VirtualCamera`.
* Atribuir essa câmera virtual: Adicione um `MainCamera` componente ao [entidade reservada](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/broken-reference) `engine.CameraEntity`, com uma referência para a entidade com o `VirtualCamera` componente.

A câmera então será anexada à entidade com o `VirtualCamera` componente. Se a entidade se mover ou girar, a câmera se move com ela.

```ts
function main() {
	const myCustomCamera = engine.addEntity()
	Transform.create(myCustomCamera, {
		position: Vector3.create(1, 2, 1),
	})
	VirtualCamera.create(myCustomCamera, {})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera,
	})
}
```

Neste exemplo, a câmera estará sempre em uma posição fixa na cena, desde que o jogador permaneça dentro dos limites da cena. Assim que o jogador sair dos limites da cena, o comportamento de câmera padrão será restaurado.

Sua cena pode incluir quantas entidades com um `VirtualCamera`componente quanto você quiser, e alternar dinamicamente entre múltiplas câmeras virtuais conforme o jogador se move, ou conforme ele realiza certas ações. Apenas uma câmera virtual está ativa a qualquer momento, isso é atribuído pelo `MainCamera` componente em `engine.CameraEntity`.

Para reverter ao comportamento de câmera padrão, defina o valor para `undefined` em `MainCamera.virtualCameraEntity`. O jogador fica então livre para alternar entre câmeras em 1ª e 3ª pessoa. Se você quiser que o jogador use apenas um desses dois modos, você pode usar um [Áreas modificadoras de câmera](#1st-and-3rd-person-camera-modes) para forçar um dos dois.

{% hint style="warning" %}
**📔 Nota**: Áreas modificadoras de câmera só têm efeito sobre o jogador se nenhuma câmera virtual estiver ativa. Se a cena estiver atualmente usando uma câmera virtual e o jogador entrar em uma área modificadora de câmera, nada acontece.

Se um modelo 3D inclui um `camera` nó como parte de seu conteúdo, isto não pode ser usado pelo SDK. Você deve criar todas as câmeras como entidades com o SDK.
{% endhint %}

```ts
function main() {
	// câmera virtual customizada
	const myCustomCamera = engine.addEntity()
	Transform.create(myCustomCamera, {
		position: Vector3.create(1, 2, 1),
	})
	VirtualCamera.create(myCustomCamera, {})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera,
	})

	// cubo clicável
	const clickCube = engine.addEntity()
	Transform.create(clickCube, { position: Vector3.create(8, 0, 8) })
	MeshRenderer.setBox(clickCube)
	MeshCollider.setBox(clickCube)
	pointerEventsSystem.onPointerDown(
		{
			entity: clickCube,
			opts: { button: InputAction.IA_POINTER, hoverText: 'Redefinir câmera' },
		},
		() => {
			// redefinir câmera para o comportamento padrão
			const mainCamera = MainCamera.getMutable(engine.CameraEntity)
			mainCamera.virtualCameraEntity = undefined
		}
	)
}
```

{% hint style="info" %}
**💡 Tip**: Quando a câmera se afasta do avatar, muitas vezes é uma boa prática também congelar os movimentos do avatar. Dessa forma o jogador não se move às cegas em direção a obstáculos. Veja [Input Modifiers](https://github.com/decentraland/docs/blob/main/creator/sdk7/interactivity/player-avatar.md#freeze-the-player)
{% endhint %}

## Visão aérea

Você pode usar uma câmera virtual para olhar a cena de uma vista top-down; isso pode ser uma variação divertida da perspectiva normal do seu avatar e permitir diferentes mecânicas de jogo.

Você deve evitar posicionar uma câmera olhando perfeitamente para baixo. Em vez disso, incline sempre a câmera levemente, mesmo 1 grau é suficiente. Isso porque os controles de direção do jogador são baseados na perspectiva da câmera, não na orientação do avatar. Se a câmera estiver olhando de uma vista aérea perfeita, não há uma definição clara de qual direção é qual. Uma inclinação imperceptível de 1 grau é suficiente para estabelecer uma direção para frente.

```ts
function main() {
	// câmera em vista aérea
	const myCustomCamera = engine.addEntity()
	Transform.create(myCustomCamera, {
		position: Vector3.create(8, 5, 8),
		rotation: Quaternion.Euler(0, 0, 91) 
		// Observe que a rotação é 91º, não 90º
	})
	VirtualCamera.create(myCustomCamera, {})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera,
	})
}
```

## Transições de câmera

Sempre que a cena alterna entre câmeras virtuais, ou entre o comportamento de câmera padrão e câmeras virtuais, os jogadores veem uma transição. A posição, rotação e quaisquer outros parâmetros da câmera virtual mudam suavemente ao longo de um período de tempo.

As configurações de transição em uma câmera virtual determinam como você faz a transição *para* essa câmera, a partir de qualquer outra câmera na cena, incluindo a padrão. Elas não afetam como você faz a transição *para fora* dessa câmera.

```ts
VirtualCamera.create(myCustomCamera1, {
	defaultTransition: { transitionMode: VirtualCamera.Transition.Time(6) },
})
```

{% hint style="info" %}
**💡 Tip**: Para evitar ter uma transição e alternar instantaneamente para uma câmera, defina o tempo de transição ou a velocidade para 0.
{% endhint %}

Dependendo do seu caso de uso, você pode preferir definir a velocidade da transição em vez da duração:

* **Tempo Fixo**: Você define a duração da transição; a câmera se moverá tão rápido quanto necessário para completar o percurso nesse período de tempo.
* **Velocidade Fixa**: Você define quão rápido deseja que a câmera virtual se mova durante a transição; a duração dependerá da distância. O valor usado para velocidade é interpretado como **metros por segundo**.

Abaixo estão exemplos para ambos os modos de transição:

```ts
// duração fixa
VirtualCamera.create(myCustomCamera1, {
	defaultTransition: { transitionMode: VirtualCamera.Transition.Time(6) },
})

// velocidade fixa
VirtualCamera.create(myCustomCamera1, {
	defaultTransition: { transitionMode: VirtualCamera.Transition.Speed(3) },
})
```

Abaixo está um exemplo completo com duas câmeras virtuais e transições entre elas:

```ts
function main() {
	// câmera virtual customizada 1
	const myCustomCamera1 = engine.addEntity()
	Transform.create(myCustomCamera1, {
		position: Vector3.create(1, 2, 1),
	})
	VirtualCamera.create(myCustomCamera1, {
		defaultTransition: { transitionMode: VirtualCamera.Transition.Time(1) },
	})

	// câmera virtual customizada 2
	const myCustomCamera2 = engine.addEntity()
	Transform.create(myCustomCamera2, {
		position: Vector3.create(1, 2, 1),
	})
	VirtualCamera.create(myCustomCamera2, {
		defaultTransition: { transitionMode: VirtualCamera.Transition.Time(3) },
	})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera,
	})

	// cubo clicável
	const clickCube = engine.addEntity()
	Transform.create(clickCube, { position: Vector3.create(8, 0, 8) })
	MeshRenderer.setBox(clickCube)
	MeshCollider.setBox(clickCube)
	pointerEventsSystem.onPointerDown(
		{
			entity: clickCube,
			opts: { button: InputAction.IA_POINTER, hoverText: 'Redefinir câmera' },
		},
		() => {
			// redefinir câmera para o comportamento padrão
			const mainCamera = MainCamera.getMutable(engine.CameraEntity)
			mainCamera.virtualCameraEntity =
				mainCamera.virtualCameraEntity == myCustomCamera1
					? myCustomCamera2
					: myCustomCamera1
		}
	)
}
```

As transições sempre se movem em linha reta, sem considerar quaisquer obstáculos no caminho. Você poderia em vez disso criar uma transição manualmente usando outra câmera virtual como intermediária; dessa forma você teria controle total sobre seus movimentos. Essa câmera virtual intermediária poderia executar um [Tween](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/broken-reference) da posição da primeira câmera para a posição da segunda câmera, ou seguir um caminho mais personalizado que evite obstáculos ou faça um desvio cinematográfico.

## Câmera seguindo

Você pode configurar uma câmera virtual para que ela sempre aponte na direção do jogador, ou de alguma entidade específica na cena. A posição da câmera permanecerá estática, mas sua rotação mudará para manter essa entidade sempre centralizada.

Isso pode ser alcançado com o `lookAtEntity` no `VirtualCamera` componente. Para seguir o jogador, use o [entidade reservada](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/broken-reference) `engine.PlayerEntity`.

```ts
const myCustomCamera1 = engine.addEntity()
Transform.create(myCustomCamera1, {
	position: Vector3.create(1, 2, 1),
})
VirtualCamera.create(myCustomCamera1, {
	lookAtEntity: engine.PlayerEntity,
})
```

Se uma entidade estiver sendo seguida pela câmera, isso apenas mudará a rotação, não a posição da câmera.

À medida que a câmera gira, o Transform da entidade com o `VirtualCamera` componente não muda. No entanto, você pode ler a rotação da câmera a partir do Transform em `engine.CameraEntity`. A rotação e a posição dessa entidade serão absolutas; não estarão condicionadas pela da entidade com o `VirtualCamera` componente. A rotação desse transform é afetada pelo `lookAtEntity` comportamento.

{% hint style="warning" %}
**📔 Nota**: Se você configurar a câmera virtual com um `lookAtEntity` que referencia a mesma entidade que possui a câmera virtual, ou a `engine.MainCamera` entidade, o comportamento resultante será o mesmo que não atribuir nenhuma entidade.
{% endhint %}

## Anexar ao jogador

Outro uso da câmera virtual é seguir o jogador a partir de uma distância ou ângulo personalizados, anexando uma câmera virtual à entidade do jogador. Note que o jogador não pode alterar livremente a rotação da câmera, então neste caso a rotação da câmera será fixa à da câmera virtual. Isso pode ser útil, por exemplo, para jogos de corrida, onde espera-se que o jogador sempre olhe para frente.

```ts
function main() {
	const myCustomCamera = engine.addEntity()
	Transform.create(myCustomCamera, {
		position: Vector3.create(0, 1, 5),
		parent: engine.PlayerEntity,
	})
	VirtualCamera.create(myCustomCamera, {
		defaultTransition: { transitionMode: VirtualCamera.Transition.Time(2) },
	})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera,
	})
}
```

## Câmeras e colliders

Quando a câmera do jogador se move em modo terceira pessoa, a câmera pode ser bloqueada por colliders ou não, dependendo das camadas de colisão atribuídas às entidades. Tenha isso em mente ao projetar sua cena; você pode querer impedir que a câmera atravesse paredes ou outras entidades.

Veja [Colliders](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/broken-reference) para mais detalhes sobre como configurar colliders para sua cena.
