본문 바로가기

로블록스 개발 중급

여러 오브젝트 사용되는 스크립트의 관리(2)

HP물약 리스트 반복문에 사용하기

앞선 튜토리얼에서 GetChildren() 함수의 반환값으로 HP물약 리스트를 얻었다. 여기서는 반복문을 사용하여 각 HP물약 오브젝트들에게 Touched 이벤트에 함수를 연결해줄 것이다. 이렇게 하면 게임이 시작하면 HealthPickups 폴더의 모든 게임오브젝트에 대해서 Touched 이벤트에 함수를 연결해줄 수 있다.

루아의 리스트를 for문에서 사용하는 문법은 다음과 같다.

  • Index(인덱스): 1부터 시작해서 리스트의 길이까지의 값을 가진다. 사용하지 않을때는, _ 을 넣어두면 된다.
  • Value(값): 리스트의 해당 인덱스의 값이다. 리스트안에 들어가있는 요소들의 값이므로 각 요소에 대한 이름으로 해두자.
  • Array(리스트): 반복시킬 리스트. ipairs() 함수에 넣어주면 for문에 사용할 수 있다.
local function onTouchHealthPickup(otherPart, healthPickup)
    local character = otherPart.Parent
    local humanoid = character:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
        humanoid.Health = MAX_HEALTH
    end
end

-- 인덱스는 사용하지 않을 것이므로 _
for _, healthPickup in ipairs(healthPickups) do
    healthPickup.Touched:Connect(function(otherPart)
    	onTouchHealthPickup(otherPart, healthPickup)
    end)
end

각 HP물약에 대해서, Touched 이벤트에 연결할 Anonymous 함수를 선언했다. 이 함수의 기능은 onTouchHealthPickup()함수를 호출하는 것이다. 왜 onTouchHealthPickup() 함수를 직접 Touched 이벤트에 연결하지 않고 Anonymous함수 안에서 호출하는 방식을 사용했을까?

 

알다시피 Touched이벤트에 연결될 함수의 파라메터로는 otherPart, 즉, Touched 이벤트를 발생시킨 파트만 파라메터로 보낼 수 있다. onTouchedHealthPickup()함수는 otherPart와 healthPickup(HP 물약 객체) 두개가 필요하기 때문에 otherPart를 파라메터로 가지는 Anonymous() 함수로 감싸고 healthPickup도 같이 onTouchHealthPickup() 함수로 보내줄 수 있게 한다. 이런 방식의 함수를 wrapper함수라고 한다. 별다른 기능은 없고 그저 다른 함수를 호출하기 위해 존재하는 함수이다.

 

테스트를 해보자. 아래 이미지처럼 하수구 뚜껑의 수증기위에 서 있으면 플레이어의 HP가 줄어든다. 줄어든 HP의 양을 보여주는 HP바는 스크린의 오른쪽 위에 표시된다. HP가 가득 차 있을때는 표시되지 않는다. 그래서 HP물약을 획득하면 HP바가 사라지게 된다.

 

HP물약 쿨타임

HP물약의 쿨타임을 적용시켜주자. 

HP물약마다 상태 변수가 필요해졌다. HP물약은 보통상태였다가, 플레이어가 터치하면 쓰여진 상태로 바뀌고, 쿨타임이 차면 다시 보통상태가 될 것이다. 해당 기능을 구현하기 위해서 각 HP물약(pickup)에게 Enabled라는 attribute를 추가 셋팅한다. GetAttribute() 와 GetAttribute()함수를 통해 오브젝트 자체에 attribute를 바로 추가할 수 있다는 것을 이전 튜토리얼(UI로 점수 보여주기)에서 배웠다. 우선은 처음 로드될 때는 Enabled 를 true로 초기화하고 플레이어가 획득했을때 true인 상태일 때만 획득가능하게 끔 바꾸자.

local function onTouchHealthPickup(otherPart, healthPickup)
    if healthPickup:GetAttribute("Enabled") then
        local character = otherPart.Parent
        local humanoid = character:FindFirstChildWhichIsA("Humanoid")
        if humanoid then
            humanoid.Health = MAX_HEALTH
        end
    end
end
 
for _, healthPickup in ipairs(healthPickups) do
    healthPickup:SetAttribute("Enabled", true)
    healthPickup.Touched:Connect(function(otherPart)
        onTouchHealthPickup(otherPart, healthPickup)
    end)
end

획득처리된 HP물약을 그대로 두면 획득가능한 상태인지 아닌지 플레이어가 오해할 수 있다. 따라서 획득처리된 HP물약은 이미 획득처리되었음을 알 수 있게 바꿔주자. 

  • Enabled 가 true일 때, 투명도는 ENABLED_TRANSPARENCY = 0.4
  • Enabled 가 false일 때, 투명도는 DISABLED_TRANSPARENCY = 0.9

HP물약의 쿨타임은 20초로 정해주자.

  • COOLDOWN = 20
local ENABLED_TRANSPARENCY = 0.4
local DISABLED_TRANSPARENCY = 0.9
local COOLDOWN = 20

 

HP물약이 획득처리되면 투명도를 DISABLED_TRANSPARENCY로 바꾸고 Enabled를 false 바꾼다. 그리고 wait(COOLDOWN)으로 그 상태에서 20초간 기다린다. 그리고 나서 다음으로 투명도를  ENABLED_TRANSPARENCY로 바꿔주고 Enabled를 true로 다시 바꿔주면 쿨타임을 구현한 HP물약이 완성이다.

local function onTouchHealthPickup(otherPart, healthPickup)
    if healthPickup:GetAttribute("Enabled") then 
        local character = otherPart.Parent
        local humanoid = character:FindFirstChildWhichIsA("Humanoid")
        if humanoid then
            humanoid.Health = MAX_HEALTH
            healthPickup.Transparency = DISABLED_TRANSPARENCY
            healthPickup:SetAttribute("Enabled", false)
            wait(COOLDOWN)
            healthPickup.Transparency = ENABLED_TRANSPARENCY
            healthPickup:SetAttribute("Enabled", true)
        end
    end
end

테스트를 통해 원하는 기능이 잘 작동하는지 확인해보자.

 

정리

  • 여러 개의 HP물약의 기능을 하나의 스크립트로 구현하였다.
  • 리스트를 반복시키는 방법을 알아보았다.

'로블록스 개발 중급' 카테고리의 다른 글

버튼 만들기  (0) 2021.04.28
스코어 바 만들기(2)  (0) 2021.04.27
스코어 바 만들기(1)  (0) 2021.04.27
세이브와 로드  (0) 2021.04.26
여러 오브젝트 사용되는 스크립트의 관리(1)  (1) 2021.04.23