製作一個敵人跟隨攻擊的功能

 

功能效果展示

 

 

運行環境

Win7,Win8,Win10

Reworld版本 體驗版

vc_redist.x64 運行環境

 

針對零基礎讀者的補充

下載安裝 Reworld對應版本

Reworld官網鏈接http://www.reworlder.com/

下載後安裝後註冊賬號打開空地圖

下載安裝 vc_redist.x64.rar運行環境

redist.x64下載鏈接

 

思路分析

敵人自動跟隨攻擊玩家的功能實現主要分爲兩部分:

第一部分;實現敵人自動索敵,實現敵人雷達系統用來判定玩家和自己的距離,然後開始自動跟隨玩家的功能。

第二部分:實現敵人這個角色的攻擊動作表現,此處就涉及到角色動作替換的技巧。

綜合以上兩部分,我們實現敵人自動跟隨並且攻擊玩家的功能思路應該爲:敵人判斷玩家和自己的距離,當距離小於某個數值時,敵人開始自動跟隨玩家,此時敵人執行的動作是奔跑動作。隨着敵人的不斷接近,敵人和玩家之間的距離縮小至敵人的攻擊範圍內時,敵人開始執行攻擊動作。

 

敵人搭建

一、搭建過程

首先我們需要在工作區裏面創建一個角色,並且給這個角色命名爲Enemy,咱們的敵人一號就出現啦。

 

好的,敵人創建好了,我們需要給敵人添加攻擊的動作,這樣敵人就可以對玩家進行攻擊了,如下圖步驟,我們創建一個動作並把名稱重命名爲attack,在攻擊動作下方把本地動作名修改爲attack,這樣敵人就擁有攻擊表現啦。如果想讓角色有不同的動作,只要在動作下將本地動作名修改成和Reworld動作列表大全中對應的動作名即可,例如:lianxupikan(連續劈砍),beijidao(被擊倒),tiaowu(跳舞)等動作。(Reworld動作列表大全

 

二、補充說明

1.什麼是工作區?

工作區中的對象是會被可視化顯示到3D場景中的,並且只有在工作區中的對象纔會發生物理交互。

服務對象。

不可創建。

不可複製。

不可刪除。

 

2.什麼是角色?

角色Avatar是一個特殊對象,它使模型具有物理走動和與各種組件交互的能力。Avatar作爲父級,使用零件作爲其子級組合成人體模型。默認情況下,Avatar的人體模型通常由:頭、左手、左大碧、右大腿、右小腿、左大腿、左小腿、右手、右大臂、左腳、右腳、臀部、胸等13個部位組成,部位缺失或名稱不符時,皆默認爲缺失,在角色加載到客戶端時,缺失部位爲空。

添加自定義的外觀時,保證其名稱符合默認部位名稱即可,並可添加衣服、配件等改變外觀效果。 人物模型的物理交互都通過Avatar產生。

如何創建角色: 點擊工作區WorkSpace後的"+",在可添加的對象中選擇角色,可直接創建基礎角色。

角色的特性:

角色由骨骼和零件構成,控制器控制其狀態。

角色的每個身體部位(自定義零件)都有自己獨立的剛體屬性(尚未實現)。

角色的身體部位通過命名規則來對應自己的骨骼,命名規則見身體部位。

角色的各項屬性都可以在角色參數組件中快速定義。

角色當前生命值爲0時角色死亡,死亡時有布娃娃和碎裂兩種效果可供選擇,角色死亡後會在出生點復活。

運行後的角色屬性由玩家初始化中的平臺自定義角色來控制,外觀來自平臺,當在平臺自定義角色之前創建一個角色對象則運行時生成該角色。

 

3.什麼是動作?

角色對象的動作對象。

動作功能:

動作對象放在相應的角色對象下即可被該角色調用(也可放在角色子級的動作文件夾、角色配件或者工具下)。

動作ID爲動作對象的地址。

動作名爲狀態機中的動作名,修改此屬性可以把當前動作設置爲受指定狀態觸發的動作;這是一個枚舉類型,例如上傳一個動作A,動作ID選擇動作A的資源ID,動作名選擇跑步,則運行后角色的跑步動作將被替換爲動作A

本地動作名爲reworld\Client\Assets\Resources\animation目錄下的動作名稱,填寫相應動作名稱即可調用相應的本地動作。

動作優先級:在動作名選擇無的情況下才生效(狀態機中所有動作的4個部位優先級均爲0),通過改變優先級可以改變身體相應4個部位播放的動作,狀態機中基礎動作優先級均爲0,優先級越大越優先,同級後者優先。

角色狀態有:站立、跑步、起跳、下落、攀爬、坐下、駕駛,在角色對象下默認有對應每種狀態的動作。

 

核心功能執行環境搭建

一、搭建過程

接下來我們需要創建一個服務器腳本,在腳本里我們需要實現敵人雷達系統用來判定玩家和自己的距離,看看有沒有到達自己的索敵區域。

腳本創建好了,接下來就是去實現它的功能了,我把腳本功能放到下方的代碼中:


local DISTANCE=5
local Enemy = WorkSpace.Enemy
local TableList=nil
local IgnoreList={} --要忽略檢索的物體表
 
local trigger=false 
 
local avatar=nil --存儲被找到的玩家
 
--合併表格方法
function MergeTables(...)
    local tabs = {...}
    if not tabs then
        return {}
    end
    local origin = tabs[1]
    for i = 2,#tabs do
        if origin then
            if tabs[i] then
                for k,v in pairs(tabs[i]) do
                    table.insert(origin,v)
                end
            end
        else
            origin = tabs[i]
        end
    end
    return origin
end
 
 
Players.PlayerAdded:Connect(function(Uid)
    local ren = Players:GetPlayerByUserId(Uid)
    ren.AvatarAdded:Connect(function()
            MergeTables(IgnoreList,Enemy:GetAllChild(),Enemy.動作:GetAllChild())--將表格信息合併到ignorelist中
            MergeTables(IgnoreList,ren.Avatar:GetAllChild(),ren.Avatar.動作:GetAllChild(),ren.Avatar.第一人稱:GetAllChild())
            trigger=true
    end)
end)
 
function Radar()
    --判定檢索範圍
    local _StartPos=Vector3.New(Enemy.Position.x-DISTANCE,Enemy.Position.y-DISTANCE,Enemy.Position.z-DISTANCE)
    local _EndPos=Vector3.New(Enemy.Position.x+DISTANCE,Enemy.Position.y+DISTANCE,Enemy.Position.z+DISTANCE)
    --雷達監測範圍內物體,忽略掉IgnoreList表中儲存的物體
    TableList=WorkSpace:FindPartsInZoneWithIgnoreList(_StartPos,_EndPos,IgnoreList,100) 
    if TableList~=nil then
        for i=1,#TableList,1 do
            if TableList[i]:IsClass("Avatar") and  TableList[i].Name~="Enemy" then --這裏做個剔除,剔除掉敵人自身
                avatar=TableList[i] --將獲取到的玩家信息做一個記錄存儲
                return true
            end
        end
    end
    avatar=nil
    return false
end
 
function EnemyAttack()
    if avatar~=nil then
        local rot= avatar.Position-Enemy.Position
        Enemy:Move(Vector2(Vector3.Normalize(rot).x,Vector3.Normalize(rot).z))
        --如果敵人和人物的距離小於0.5
        if  Vector3.Distance(Enemy.Position,avatar.Position)<0.5 then
            --敵人停止移動,改爲攻擊
            Enemy:Move(Vector2(0,0))
            Enemy.動作.attack.Action= Enum.AnimationType.stand
            Enemy.動作.attack.LocalClipId ="attack"
        end
    end
end
 
GameRun.Update:Connect(function()
    if trigger==true and Radar() then
        EnemyAttack()
    end
end)

有些時候將腳本複製到編輯器中可能會出現問題,可以用TXT文檔轉換一下,或者刪掉重新創建一個腳本試試,另外有些時候會出現複製不上的情況,這個時候可以關閉腳本編輯重新打開就可以了。

 

二、補充說明

1.什麼是服務器腳本?

只會在服務器運行的Lua腳本代碼,用於編寫服務器邏輯。

 

2.爲什麼要使用服務器腳本?

基於敵人跟隨攻擊功能用於單人和多人等不同環境,所以採用通用的服務器腳本。

  1. 服務器腳本與客戶端腳本不同,客戶端執行的操作只有本地客戶端,也就是玩家自己有效。而服務器執行的操作不僅針對單人有效,還針對與服務器相連的所有客戶端同步生效。
  2. 在多人遊戲中,如果這個對象的變化是針對一個人的,必須在客戶端腳本進行編寫;如果這個對象的變化是針對所有人的,那就必須在服務器腳本進行編寫。
  3. 對於只能在客戶端腳本修改的對象,如何讓服務器知曉變化結果是很重要的。這裏採用傳統遊戲的製作流程,也就是在客戶端進行修改,把修改後的結果通過與服務器通信的方式發送到服務器,再通過服務器進行邏輯運算,把執行結果再同步給所有客戶端。

好了,接下來我們點擊開始遊戲就可以了,記得把敵人放置的離玩家遠一些,當你悄悄的靠近敵人的時候,進入到了索敵區域,敵人就會轉身跑到你的身邊攻擊你啦。記得趕緊跑~~~

如果有什麼問題或者有更好的實現方式,大家可以在下方積極交流討論,我們也會參與進來和大家一起分享經驗,期望能和大家共同進步~~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章