본문 바로가기
Learn

Camera Manipulation

by Roblox_개발자 2021. 4. 24.

기본 카메라 커스텀 외에도 게임 카메라를 조작하여 특정 플레이어 / 캐릭터보기 시스템을 만들고 카메라를 World 위치에 고정하고 고 한 카메라 효과를 만드는 등의 작업을 수행 할 수 있다.

Camera Properties (카메라 속성)

로블록스 Camera는 여러 내장 속성을 가진다.

 

Property Description
Camera.CFrame 카메라의 CFrame. 이 속성은 카메라를 이동시키는데 자주 사용된다.
Camera.Focus 3D 공간에서 카메라가 바라보는 지점. 카메라를 특정 방향으로 가리킬 때는 특정 시각 효과가 초점 지점에 얼마나 가까운지에 따라 더 자세해지므로이 속성을 업데이트해야한다.
Camera.FieldOfView 화면에서 볼 수있는 관찰 가능한 게임 세계의 범위, 세로 방향으로 1 ~ 120도 사이에서 측정. (기본은 70)

 

Scripting the Camera (카메라 스크립팅하기)

스크립트내에서, 게임 카메라는 CurrentCamera 객체로 접근할 수 있다.

local camera = workspace.CurrentCamera
각 플레이어의 카메라는 디바이스에 로컬이기 때문에 커스텀 카메라 코드는 StarterPlayerScripts 또는 StarterPack 내의 LocalScript에 있어야한다. 스크립트를 다른 곳에 배치하면 코드가 카메라를 제대로 제어 할 수 없다.

 

Over-the-Shoulder

3인칭 슈팅 게임에서 흔히 볼 수있는 기본 Over-the-Shoulder 카메라는 다음 스크립트로 얻을 수 있다. 이 카메라는 캐릭터의 등 뒤에 고정되어 있으며 플레이어는 마우스를 사용하여 회전한다 (방향 입력이 아님).

local Players = game:GetService("Players")
local ContextActionService = game:GetService("ContextActionService")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
 
local camera = workspace.CurrentCamera
local cameraOffset = Vector3.new(2, 2, 8)
local player = Players.LocalPlayer
 
player.CharacterAdded:Connect(function(character)
 
	local humanoid = character:WaitForChild("Humanoid")
	local rootPart = character:WaitForChild("HumanoidRootPart")
	humanoid.AutoRotate = false
 
	local cameraAngleX = 0
	local cameraAngleY = 0
 
	local function playerInput(actionName, inputState, inputObject)
		-- Calculate camera/player rotation on input change
		if inputState == Enum.UserInputState.Change then
			cameraAngleX = cameraAngleX - inputObject.Delta.X
			-- Reduce vertical mouse/touch sensitivity and clamp vertical axis
			cameraAngleY = math.clamp(cameraAngleY-inputObject.Delta.Y*0.4, -75, 75)
			-- Rotate root part CFrame by X delta
			rootPart.CFrame = rootPart.CFrame * CFrame.Angles(0, math.rad(-inputObject.Delta.X), 0)
		end
	end
	ContextActionService:BindAction("PlayerInput", playerInput, false, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch)
 
	RunService.RenderStepped:Connect(function()
		if camera.CameraType ~= Enum.CameraType.Scriptable then
			camera.CameraType = Enum.CameraType.Scriptable
		end
		local startCFrame = CFrame.new((rootPart.CFrame.Position)) * CFrame.Angles(0, math.rad(cameraAngleX), 0) * CFrame.Angles(math.rad(cameraAngleY), 0, 0)
		local cameraCFrame = startCFrame:ToWorldSpace(CFrame.new(cameraOffset.X, cameraOffset.Y, cameraOffset.Z))
		local cameraFocus = startCFrame:ToWorldSpace(CFrame.new(cameraOffset.X, cameraOffset.Y, -10000))
		camera.CFrame = CFrame.new(cameraCFrame.Position, cameraFocus.Position)
	end)
end)
 
local function focusControl(actionName, inputState, inputObject)
	-- Lock and hide mouse icon on input began
	if inputState == Enum.UserInputState.Begin then
		UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
		UserInputService.MouseIconEnabled = false
		ContextActionService:UnbindAction("FocusControl", focusControl, false, Enum.UserInputType.MouseButton1, Enum.UserInputType.Touch, Enum.UserInputType.Focus)
	end
end
ContextActionService:BindAction("FocusControl", focusControl, false, Enum.UserInputType.MouseButton1, Enum.UserInputType.Touch, Enum.UserInputType.Focus)
7번줄에있는 cameraOffset 값을 확인하자. 예를 들어 이 값을 조정해서 캐릭터의 왼쪽 어깨 (-2, 2, 8) 위에 배치하거나 플레이어에서 카메라를 더 멀리 당기는 등 카메라의 상대적 위치를 캐릭터에 맞게 조정할 수 있다. (2, 2, 15).

 

Scope In/Out

다음 스크립트를 사용하여 간단한 scope in/out 카메라 시스템을 구현할 수 있다. 이 예제에서는 마우스 가운데 단추를 사용하여 확대 및 축소하고 ContextActionService 기능을 사용하여 모바일 장치에서 가상 확대 / 축소 버튼으 만든다.

local Players = game:GetService("Players")
local ContextActionService = game:GetService("ContextActionService")
local UserInputService = game:GetService("UserInputService")
local TweenService = game:GetService("TweenService")
 
local camera = workspace.CurrentCamera
local player = Players.LocalPlayer
 
local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Quint, Enum.EasingDirection.Out)
local initialFieldOfView = camera.FieldOfView
local initialCameraPosition = camera.CFrame
local isZoomed = false
local inTween = false
local target
 
player.CharacterAdded:Connect(function(character)
 
	local humanoid = character:WaitForChild("Humanoid")
	local rootPart = character:WaitForChild("HumanoidRootPart")
	local initialWalkSpeed = humanoid.WalkSpeed
	local initialJumpPower = humanoid.JumpPower
 
	local cameraAngleX = 0
	local cameraAngleY = 0
 
	local function moveInput(actionName, inputState, inputObject)
		if not isZoomed then return end
		if inputState == Enum.UserInputState.Change then
			cameraAngleX = math.clamp(cameraAngleX-inputObject.Delta.X*0.4, -90, 90)
			cameraAngleY = math.clamp(cameraAngleY-inputObject.Delta.Y*0.4, -75, 75)
			local camPosition = rootPart.CFrame:ToWorldSpace(CFrame.new(0, 2, -2))
			local camRotation = camPosition * CFrame.Angles(0, math.rad(cameraAngleX), 0) * CFrame.Angles(math.rad(cameraAngleY), 0, 0)
			target = camRotation:ToWorldSpace(CFrame.new(0, 0, -20))
			camera.CFrame = CFrame.new(camRotation.Position, target.Position)
			camera.Focus = CFrame.new(target.Position)
		end
	end
 
	local function scopeInOut(actionName, inputState, inputObject)
		if inTween == true then return end
		if (inputObject.UserInputType == Enum.UserInputType.MouseButton3 and (inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.End))
			or (inputObject.UserInputType == Enum.UserInputType.Touch and inputState == Enum.UserInputState.End) then
			inTween = true
			-- Zoom in
			if isZoomed == false then
				initialCameraPosition = camera.CFrame
				camera.CameraType = Enum.CameraType.Scriptable
				UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
				UserInputService.MouseIconEnabled = false
				-- Rotate root part CFrame according to camera direction
				local faceToward = camera.CFrame:Lerp(rootPart.CFrame, 1.1)
				rootPart.CFrame = CFrame.new(rootPart.CFrame.Position, Vector3.new(faceToward.Position.X, rootPart.Position.Y, faceToward.Position.Z))
				target = rootPart.CFrame:ToWorldSpace(CFrame.new(0, 2, -20))
				cameraAngleX, cameraAngleY = 0, 0
				humanoid.WalkSpeed = 0
				humanoid.JumpPower = 0
				wait(0.05)
				local camPosition = rootPart.CFrame:ToWorldSpace(CFrame.new(0, 2, -2))
				camera.CFrame = CFrame.new(camera.CFrame.Position, target.Position)
				local tween = TweenService:Create(camera, tweenInfo, {CFrame=camPosition, FieldOfView=12})
				tween.Completed:Connect(function()
					ContextActionService:BindAction("MoveInput", moveInput, false, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch)
					ContextActionService:SetTitle("ScopeInOut", "–")
					camera.Focus = CFrame.new(target.Position)
					isZoomed = true
					inTween = false
				end)
				tween:Play()
			-- Zoom out
			elseif isZoomed == true then
				ContextActionService:UnbindAction("MoveInput", moveInput, false, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch)
				UserInputService.MouseBehavior = Enum.MouseBehavior.Default
				UserInputService.MouseIconEnabled = true
				local tween = TweenService:Create(camera, tweenInfo, {CFrame=initialCameraPosition, FieldOfView=initialFieldOfView})
				tween.Completed:Connect(function()
					ContextActionService:SetTitle("ScopeInOut", "+")
					camera.CameraType = Enum.CameraType.Custom
					humanoid.WalkSpeed = initialWalkSpeed
					humanoid.JumpPower = initialJumpPower
					isZoomed = false
					inTween = false
				end)
				tween:Play()
			end	
		end
	end
	ContextActionService:BindAction("ScopeInOut", scopeInOut, true, Enum.UserInputType.MouseButton3)
	ContextActionService:SetPosition("ScopeInOut", UDim2.new(0.65, 0, 0.1, 0))
	ContextActionService:SetTitle("ScopeInOut", "+")
end)

 

 

Rotate Around Object

카메라를 Part 중심으로 전체 또는 부분적으로 회전하려면 조정 가능한 카메라 오프셋, 회전 시간, 반복 횟수, easing style 등을 제공하는 다음 스크립트를 사용해라.

local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
 
local target = workspace:FindFirstChild("Part")  -- The object to rotate around
local camera = workspace.CurrentCamera
camera.CameraType = Enum.CameraType.Scriptable
local rotationAngle = Instance.new("NumberValue")
local tweenComplete = false
 
local cameraOffset = Vector3.new(0, 10, 12)
local rotationTime = 15  -- Time in seconds
local rotationDegrees = 360
local rotationRepeatCount = -1  -- Use -1 for infinite repeats
local lookAtTarget = true  -- Whether the camera tilts to point directly at the target
 
local function updateCamera()
	if not target then return end
	camera.Focus = target.CFrame
	local rotatedCFrame = CFrame.Angles(0, math.rad(rotationAngle.Value), 0)
	rotatedCFrame = CFrame.new(target.Position) * rotatedCFrame
	camera.CFrame = rotatedCFrame:ToWorldSpace(CFrame.new(cameraOffset))
	if lookAtTarget == true then
		camera.CFrame = CFrame.new(camera.CFrame.Position, target.Position)
	end
end
 
-- Set up and start rotation tween
local tweenInfo = TweenInfo.new(rotationTime, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, rotationRepeatCount)
local tween = TweenService:Create(rotationAngle, tweenInfo, {Value=rotationDegrees})
tween.Completed:Connect(function()
	tweenComplete = true
end)
tween:Play()
 
-- Update camera position while tween runs
RunService.RenderStepped:Connect(function()
	if tweenComplete == false then
		updateCamera()
	end
end)

 

10-14 행의 변수는 스크립트의 동작을 제어하기 위해 조정할 수 있다. 예를 들어 cameraOffset 벡터 값 0, 30, 12와 같이 카메라가 대상 오브젝트 위에 높은 위치에있는 경우 lookAtTarget을 true로 설정하면 카메라가 아래쪽으로 기울어져 오브젝트를 직접 볼 수 있다.

예제가 작동을 안함...

 


참고 링크

developer.roblox.com/en-us/articles/Camera-manipulation

 

Camera Manipulation

This Platform uses cookies to offer you a better experience, to personalize content, to provide social media features and to analyse the traffic on our site. For further information, including information on how to prevent or manage the use of cookies on t

developer.roblox.com

 

댓글