반응형

기본 공격느낌이 이제서야 맘에 들기 시작하네요.

기존 AnimNotify로 구현한 것들을 다시 만들었습니다.

그 결과 몽타주에 AnimNotify 수가 많이 줄어들고 넣고 싶었던 것도 반영했습니다. 무기의 콜리젼에 겹쳐지는 애들에게 데미지를 입히게 구현했고 두가지의 타입을 적용할수 있습니다.

NotifyState 사용해서 특정시간동안 계속 데미지를 입힐수 있는타입과

Notify 사용해서 한번만 데미지를 입히는 타입으로 구현했습니다.

그리고 기존과 같이 특정 모션타임에 키를 누르면 다음 공격으로 이어져 콤보공격이 가능하게 되고 공격시 어느정도의 이동도 같이 되고 있습니다.

반응형

'IndieGame Dev' 카테고리의 다른 글

Devlog #09 무기타입별 경직&밀리는 정도  (0) 2021.08.23
다크매터 프롤로그  (0) 2021.06.06
Devlog #07 Weapons-specific animation  (0) 2020.12.27
Devlog #06 레벨 목업 작업  (0) 2020.11.17
Devlog #05 영상 편집본  (0) 2020.11.17
반응형

FBX 익스포트 (2017버전 기준)

  1. 스킨적용된 메쉬 익스포트
  2. 한 파일안의 애니메이션을  특정구간별 익스포트
  3. 마지막으로 선택한 디렉토리 및 모션 값을 저장 하거나 불러오기
  4. 버그수정
    • 모디파이어 패널이 아닐때(skin modifier 못찾는것) selectObj클릭시 오류수정
    • SelectObj 클릭시 본, 헬퍼 안보이게 한것 수정.
    • selectDir 클릭후 폴더를 선택하지 않고 창을 닫을떄 오류수정
    • FrameStart 최대가 100인것 수정
    • 모션 리스트 없거나 1나만 있을떄 List_컬러체킹용 클릭시 오류수정, 개선
  5. 맥스 뷰포트에서 새로운 창 띄우고 거기에서 정해진 프레임별 애니선택 및 체크 할수 있게 제작
  6. 배치용 익스포트

사용 예시

/*
FBX Export maxscript tool
Copyright (C) 2015-2018, JinKyu Kim
This program is distributed in the hope that it will be useful.

------------------------------------------------------------------------------
-- FBX Export split animation clips in maxfile
-- By Jinkyu Kim (http://chakanz.tistory.com/, contact : chakan0000@gmail.com)
-- Created On: 2015-04-08
-- tested using  Max 2017
-------------------------------------------------------------------------------
*/

global FBX_Export 

try
    (   makedir (   (getdir #scripts) + @"\tmp\") ) catch   (print "error~~~~~~~~~~~~~")
    
    
-- 익스포트될 디렉토리 저장.
    Global inifilepath  =   (getdir #scripts )+ @"\tmp\Export_Setting.ini"

-- 배치용 디렉토리 저장.
    Global iniSourceFilepath    =   (getdir #scripts )+ @"\tmp\SourceFile_Setting.ini"

-- 애니메이션 리스트 저장
    Global aniSettingPath   =   maxfilepath+getFilenameFile maxfilename+ @".ini"
/*  
--  파일이름 관련  예시.
--  file="g:\\subdir1\\subdir2\\myImage.jpg"
--  filenameFromPath file -- returns: "myImage.jpg"
--  getFilenamePath file -- returns: "g:\subdir1\subdir2\"
--  getFilenameFile file -- returns: "myImage"
--  getFilenameType file -- returns: ".jpg"
--  pathIsNetworkPath "c:\\temp\\test.txt" --returns: false
--  pathIsNetworkPath "\\\\someserver\\temp\\test.txt" --returns: true
*/
    
global frame = #()

-- 익스포트할때 각 확장자_타입별 클래스.
global  theClasses = exporterPlugin.classes     

try DestroyDialog FBX_Export catch()


rollout FBX_Export "FBX_EXPORT" width:300 height:700
( 
    Group "OBJ Export"
        (
            button SelectObj        "SelectObj"                 pos:[5,20]          width:140 height:35
            label   showbox         "Select for Export"     pos:[35,65]         width:200 height:50
            button  btn_SelectDir   "SelectDir"                pos:[5,115]     width:50 height:20
            edittext text_SelDir        ""                             pos:[55,115]        width:200 height:20
        )
            button ExportMesh       "ExportMesh"              pos:[5,140]     width:140 height:35
        
    Group "Ani Export"
        (       
            button bt_ExportAni     "ExportAni"                 pos:[5,530]     width:140 height:35
            button bt_LoadAni        "Load"                 pos:[160,530]     width:40 height:35
            button bt_SaveAni        "Save"                 pos:[200,530]     width:40 height:35
            edittext ed_TakeName "TakeName "                pos:[10,200]    width:140 height:15
            spinner sp_FrameStart "FrameStart "                pos:[10,220]             width:200 height:15 range:[0,9000,0]  type:#integer
            spinner sp_FrameEnd  "FrameEnd  "                pos:[10,240]      width:200 height:15  range:[0,9000,0] type:#integer
        
            button  bt_AniAdd       "ADD"                      pos:[5,260]     width:60 height:35
            button  bt_AniRemove "REMOVE"                   pos:[65,260]        width:60 height:35
            button  bt_AniReset     "RESET"                     pos:[125,260]   width:60 height:35
            Label   ed_ItemList "0개의 모션"                   pos:[10,300]        width: 200 height:15
            button  bt_listcolor    "LIST_컬러체킹용"               pos:[200,260]   width:80 height:35

            dotnetControl lv_Object "System.Windows.Forms.ListView" pos:[10,320] width:280 height:200
            Label  ed_empty "" pos:[10,565]  width:140 height:15
        )
        
    Group   "Batch Export"
        (
            button bt_BatchExport   "BatchExport"       pos:[140,630]  width:140 height:35
            button  btn_SourceDir   "SourceDir"         pos:[5,610]     width:50 height:20
            edittext text_SourceDir         ""                    pos:[55,610]    width:200 height:20
            label   created       "Create by Jinkyu kim"     pos:[185,680]         width:200 height:50
        )   
        

            
    fn SelectSkinnedBones = 
    (
--Mesh선택하기 위해서 
        hidebyCategory.helpers = true
        hidebyCategory.bones = true
        max select all      
        
--모디파이 탭 선택되고 스킨안에 포함된 본들을 선택
        max modify mode

--본, 더미 다시 보이게
        hidebyCategory.helpers = false
        hidebyCategory.bones = false
        
        if $ !=undefined  then     
        (   
                SelectMesh = $
                
                if $.modifiers[#Skin] != undefined  do               
                (
                    Tskin = $.modifiers[#Skin] 

--스킨에 적용된 본갯수
                    BoneNum = skinOps.GetNumberBones Tskin                

--배열지정
                    SkinBoneList=#()                                                            

-- 본객수만큼 반복 .
                    for i=1 to BoneNum do  
                    (  
                        
--본 이름을 배열로 넣음                      
                        SkinBoneList[i] = skinOps.GetBoneName Tskin i 1     
                    )
                    
                    clearselection
                    
--본이름 배열 개수만큼반복.
                    for i=1 to SkinBoneList.count do                                     
                    (
                        
--배열값의 이름을 얻어온다.
                        nodeSkinBone = getnodebyname SkinBoneList[i]     
                        if nodeSkinBone !=undefined do
                        (
                            selectmore nodeSkinBone
                            FBX_Export.showbox.text ="모델네임 : "+ SelectMesh.name + "  \n" +"본 개수   : "+SkinBoneList.count as string +"_Bones"
                        )
                    )
                    
                )
        )
    )


    fn SelectDir = 
    (
-- 캡션은 선택창에서 보이는 글적는것.
        Global Target = getSavePath caption:"Keep Working~!!!!!!!!!!!!!!!!!!!!!!!!!! \nSelect Directory for Export"  initialDir:FBX_Export.text_SelDir.text         
        if Target != undefined  then
        (
            FBX_Export.text_SelDir.text = Target        
        )
    )
        
    
    fn SourceDir = 
    (
        Global SourceTarget = getSavePath caption:  "익스포트할 소스폴더를 선택 하세요.!"  initialDir:(getDir #maxroot)    
        if Target != undefined  then
        (
            FBX_Export.text_SourceDir.text = SourceTarget                                                                                   
        )
    )       
            

    fn ExportObj = 
    (               
-- 겟파일네임함수로 맥스파일네임을 가지고 온다.     
        export_name = getFilenameFile maxFileName                                                                                           
        
--처음에 Target를 썻었는데 에러가 뜸. 그래서 직접 FBX_Export.text_SelDir.text  를 넣어줌
--익스포트 클래스 5번째 항목인 FBX로 익스포트. -- "\"이것만 쓰면 영역지정이 안됨. 앞에 @ 붙여주니깐 됨.
        exportFile (FBX_Export.text_SelDir.text + @"\" + export_name)    #noPrompt  using:theClasses[9] selectedOnly:true           
        print (FBX_Export.text_SelDir.text + @"\"  + export_name)                                                                                                       
    )


    fn ExportFBX_Option=
    (
        FBXExporterSetParam "SmoothingGroups" true
        FBXExporterSetParam "Animation" false
        FBXExporterSetParam "Cameras" false
        FBXExporterSetParam "Lights" false
        FBXExporterSetParam "UpAxis" "Y"
        FBXExporterSetParam "ScaleFactor" 1.0
        FBXExporterSetParam "ConvertUnit" "cm"
        FBXExporterSetParam "Skin" true

--FBXExporterSetParam "embed Media" false  --embed Media 체크시 텍스쳐를 포함하는 FBX                                                                            
        FBXExporterSetParam "ASCII" false -- binaries are smaller
    )       

    
    local layout_def = #("", "TakeName", "StartFrame", "EndFrame")

    
    fn initListView lv =  
    (
        lv.gridLines = true
        lv.View = (dotNetClass "System.Windows.Forms.View").Details
        lv.MultiSelect = true
        lv.FullRowSelect=true
        lv.backColor = (dotNetClass "System.Drawing.color").DarkKhaki   
/*      
-- lv.Checkboxes = true
-- lv.LabelEdit = true --리스트아이템의 첫번쨰 열(세로)만 됨.
-- lv.Items.Item[1].backColor =  (dotNetClass "System.Drawing.color").Green
-- lv.Items.Item[1].SubItems.Item[3].backColor =  (dotNetClass "System.Drawing.color").Yellow
*/
        for i in layout_def do    

--layout_def의 배열 값을 하나씩 가져와 가로69인  항목을 추가한다.            
            (lv.Columns.add i 69 ) 
    )


    Local Item = #()
    Local ItemClass =dotNetClass "ListViewItem"
    Local NumF

    
    fn addList lv mNumF mTakenF mStartF mEndF =
    (   
        NumF = mNumF  as string
        TakenF = mTakenF as string
        StartF = mStartF  as string
        EndF = mEndF  as string
        data = #(NumF)
 
-- data의 배열인 i가  아래 4개의 값(i, TakenF, StartF, EndF) )을 모아서 item에 전달.
        item = for i in data collect                                           
        (
            dotNetObject ItemClass  #(i, TakenF, StartF, EndF) 
        )
        lv.items.addRange item
        lv.Update()
    )


    fn ListRemove lv =
    (
        local selitem = #()
        a = lv.SelectedItems
        SelCount = a.Count

        if SelCount !=0 then
        (

-- 선택된 아이템의 갯수만큼 반복한다. 반복할때마다 선택된아이템들 아이템을 수집해서 selitem의 배열에 집어넣는다. (((i-1 은 LISTVIEW 는 0부터 시작. 맥스스크립트는 1부서 시작)))
            selitem = for i=1 to SelCount collect (a.item[i-1])  

--selitem안에 selecteditems을 삭제. 
            for i in selitem do ( lv.items.remove  i)             
        )       
        else messagebox "선택 후 클릭 하십시요~~"
    )       

        
--아이템 위치 확인용        
    fn ListViewColorCheck lv= 
    (
        if  lv.items.count !=0 do
        (
            for i=1 to  lv.items.count do
            (  
--https://developer.mozilla.org/en-US/docs/Web/CSS/color_value--컬러색보는곳
                lv.items.item[i-1].UseItemStyleForSubItems = false
                lv.items.item[i-1].subitems.item[1].backcolor = (dotNetClass "System.Drawing.color").LightPink
                lv.items.item[i-1].subitems.item[2].backcolor = (dotNetClass "System.Drawing.color").darkslateblue
                lv.items.item[i-1].subitems.item[3].backcolor = (dotNetClass "System.Drawing.color").deepskyblue
--  print lv.items.item[0].subitems.item[i].text

                
            )
        )
        
    )

/*
--  global RangeStart = animationRange.start
--  global RangeEnd = animationRange.end
*/

    fn ExportAni lv = 
    (   
        AllCount =   lv.Items.count
        ListArray = #()
               
        for i=1 to AllCount do
        
        (    
            AniName =  lv.items.item[i-1].SubItems.item[1].text
            FStart =   lv.items.item[i-1].Subitems.item[2].text
            FEnd   =   lv.items.item[i-1].Subitems.item[3].text
            _AniName    = AniName as string
            _FStar      =  FStart as integer
            _FEnd       = FEnd as integer

-- 배열을 배열에 집어 넣음.
            append ListArray #(_AniName,    _FStar, _FEnd)                            
        )
  
-- 배열안의  1번쨰 배열을 선택해서 세개의 값을 가져갈수 있도록
        for m in ListArray do                                                                  
        (   
                animationRange = interval m[2] m[3]
                FBXExporterSetParam "Animation" true 
                FBXExporterSetParam "BakeAnimation" true 
                FBXExporterSetParam "BakeFrameStart"    m[2] 
                FBXExporterSetParam "BakeFrameEnd"   m[3]
                FBXExporterSetParam "BakeFrameStep" 1.0
-- FbxExporterSetParam "BakeResampleAnimation" true
-- FbxExporterSetParam "NormalsPerPoly" false
-- FBXExporterSetParam "SplitAnimationIntoTakes" m[1] m[2] m[3]  -- #(_AniName,    _FStar, _FEnd)   --2011 버전은 없는거 같음.
                FBXExporterSetParam "Cameras" false
                FBXExporterSetParam "Lights" false
                FBXExporterSetParam "UpAxis" "Y"
                FBXExporterSetParam "ScaleFactor" 1.0
                FBXExporterSetParam "ConvertUnit" "cm"
                FBXExporterSetParam "Skin" true
                FBXExporterSetParam "ASCII" false -- binaries are smaller
                export_name = getFilenameFile maxFileName
--  FBXExporterSetParam "embed Media" false           
            
-- 처음에 Target를 썻었는데 에러가 뜸. 그래서 직접 FBX_Export.text_SelDir.text  를 넣어줌.           
                exportFile (FBX_Export.text_SelDir.text + @"\" + export_name+"_" + m[1])    #noPrompt using:theClasses[9]   selectedOnly:true   --using:theClasses[9] 맥스 버전에 따라 다름., using:FBXEXP 써도 되나봄

-- exportFile(Target + @"\" + export_name + m[1])  #noPrompt selectedOnly:boolSelOnly using:exporterPlugin.classes[intFBXID]
--  FBXExporterSetParam "SplitAnimationIntoTakes" "-c"      -- [TakeName] StartValue EndValue  값초기화.        
        )               
    )

    
--최근 위치값 설정 저장.
    fn SaveInifile _path=
    (
        setINISetting _path  "SelectedDir"  "Export_Dir"     text_SelDir.text 
    )

    
--최근 위치값 설정 불러오기..
    fn LoadInifile _path=
    (
        text_SelDir.text    =   getINISetting _path  "SelectedDir"  "Export_Dir"    
    )

    
--최근 소스파일 위치값 설정 저장.
    fn SaveIniSourcefile _path=
    (
        setINISetting _path  "SourceDir"    "_Dir"   text_SourceDir.text 
    )

    
--최근 소스파일 위치값 설정 불러오기..
    fn LoadIniSourcefile _path=
    (
        text_SourceDir.text     =   getINISetting _path  "SourceDir"    "_Dir"  
    )


--애니 설정값 저장.
    fn SaveAni_Inifile _path=
    (
--저장시 이전 기록 삭제.(기존 기록 유지시 데이타 꼬임)   
        delINISetting _path "Animation"

-- 단순히 애니파일 구분하기위한 용도.
        null = "---------------"    
        
        for i= 1 to  lv_Object.items.count do
        (
            setINISetting _path  " Animation"   (null+ i as string)                 "Take"  
            setINISetting _path  " Animation"   ("AniName" + i as string)   lv_Object.items.item[i-1].SubItems.item[1].text
            setINISetting _path  " Animation"   ("FStart"   +i as string)       lv_Object.items.item[i-1].Subitems.item[2].text
            setINISetting _path  " Animation"   ("FEnd" +i as string )         lv_Object.items.item[i-1].Subitems.item[3].text
        )
            setINISetting _path  " Animation"   (null as string)                        "Total "  
            setINISetting _path  " Animation" "Count"  (lv_Object.items.count as string)
    )


--애니 설정값 불러오기.
    fn LoadAni_Inifile _path=
    (   
        for i= 1 to getINISetting _path  " Animation" "Count" as integer do
        (
            TakeName    =   getINISetting _path  " Animation"   ("AniName"  + i as string ) 
            FrameStart  =   getINISetting _path  " Animation"   ("FStart"       +i as string)   
            FrameEnd    =   getINISetting _path  " Animation"   ("FEnd"         +i as string )  
            NumF = "선택"
            addList lv_Object NumF TakeName FrameStart FrameEnd --위 라인에서 설정한 값들을 addlist(Listview에 숫자 넣는 함수) 함수에서 실행.       
        )                       
            FBX_EXPORT.ed_ItemList.Text=  getINISetting _path  " Animation" "Count" as string +"개의 모션 "   
    )


    fn ListReset  lv =
    (
        lv.items.clear()
    )

    
--ListView 아이템 갯수
    fn listNum lv =        
    (   
        lv.items.count
    ) 
    
        
    on FBX_Export open do
    (
        print "\--------------------------------------------------------------------"
        print "open"
        try(LoadInifile inifilepath)catch()
        LoadIniSourcefile iniSourceFilepath
        initListView lv_Object
        print  inifilepath
    )   

    
    on FBX_Export close do
    (
        SaveInifile inifilepath 
        SaveIniSourcefile iniSourceFilepath
        print "\--------------------------------------------------------------------"
        print "closed"          
    )

    
    on SelectObj pressed do
    (
        SelectSkinnedBones()
    )    

    
    on btn_SelectDir pressed do
    (
        SelectDir ()
    )
    
            
    on btn_SourceDir pressed do
    (
        SourceDir  ()
    )
    
    
    on bt_SaveAni pressed do
    (
        SaveAni_Inifile aniSettingPath
    )

    
    on bt_LoadAni pressed do
    (
        
--로딩전에 리스트 리셋하기 
        ListReset lv_Object
        LoadAni_Inifile aniSettingPath
    )
    
    
    on ExportMesh pressed do
        
    (
        ExportFBX_Option()  
        ExportObj()
    )


    on bt_ExportAni pressed do
        
    (   
        ExportAni lv_Object      
    )


    local NumCount = #()
        
    
    on bt_AniAdd pressed do 
    (
        NumF = "선택"
        local TakeName =  FBX_EXPORT.ed_TakeName.Text
        local FrameStart = FBX_EXPORT.sp_FrameStart.value
        local FrameEnd =  FBX_EXPORT.sp_FrameEnd.value
            
        if (FrameStart > FrameEnd) then
        messagebox "시작 값이 끝나는값보다 작아야 됩니다."
        
        else
        (
--위 라인에서 설정한 값들을 addlist 함수에서 실행.
            addList lv_Object NumF TakeName FrameStart FrameEnd 

--입력값 초기화
            TakeName =  FBX_EXPORT.ed_TakeName.Text=""             
            FrameStart =  FBX_EXPORT.sp_FrameStart.value=0
            FrameEnd  =  FBX_EXPORT.sp_FrameEnd.value=0
            FBX_EXPORT.ed_ItemList.Text=   listNum lv_Object as string  +"개의 모션 "   
        )
    )
        
    
    on bt_BatchExport pressed do
    (
--파일에 @가 포함이면   
        bAniFile        = matchpattern maxfilename pattern:     @"*@*"      

--파일에 Mesh가 포함이면                
        bMeshFile   = matchpattern maxfilename pattern:     @"*Mesh*"           
        
        maxfiles=#()
        maxfiles    =   getFiles ( text_SourceDir.text + "\*.max")
        
        for f in maxfiles do 
        (

--  loadMaxFile() will replace the current scene content with the file content without warning!     
            loadmaxfile f           

-- 셀렉트 스킨메쉬.            
            SelectSkinnedBones()
            
--  export 메쉬
            if(bMeshFile == true) then          
                (
                    ExportFBX_Option()  
                    ExportObj()
                )
-- export 애니                
            if(bAniFile == true) then               
            (
--  LoadAni_Inifile  각각의 애니셋팅 목록값을 불러온다.
                LoadAni_Inifile aniSettingPath  
                ExportAni lv_Object                     
            )   
        )
    )


    on bt_AniReset pressed do
    (
        ListReset lv_Object
--ADD버튼을 누릴떄마다 넘버가 늘어나는데 리셋후에도 계속 늘어나 코드 추가.    
        NumCount = #()    
        FBX_EXPORT.ed_ItemList.Text=   listNum lv_Object as string  +"개의 모션 "
    )
        

    on bt_AniRemove pressed do
    (
                ListRemove lv_Object
                FBX_EXPORT.ed_ItemList.Text=   listNum lv_Object as string  +"개의 모션 "
    )
        

    on bt_listcolor pressed do
    (
        ListViewColorCheck  lv_Object
    )

)

createdialog FBX_Export

 

 

 

 

FBX_Export_split_animationClips_in_maxfile.ms

 

drive.google.com

 

반응형

'Script > MaxScript' 카테고리의 다른 글

Pos2VertexColor for Foliage Animation wip  (0) 2020.06.19
pos2zero  (0) 2019.10.11
Random_Scatter_Surface  (0) 2019.10.11
TRI,VERTEX Viewport Count  (0) 2019.10.11
반응형

Zbrush <-> 3dsMax -> UE4(BP&Material)

 

더보기

 

이 버전에선 파란 메쉬 개별 선택이 가능해서(피봇이 각각의 중심) 시뮬레이션 플레이로 움직이면서 확인 가능했는데

 

이 버전에선 파란메시가 전체선택밖에 안되네.그래서 최상위 피봇으로 나옴. 근데 파란메쉬  bp에서 선택후 피봇 움직이면 피봇이 해당 위치로 이동. 버그같음.

 

 

 

반응형

'Material, BluePrint > with Blueprint' 카테고리의 다른 글

Simple Crowd for cinematic  (0) 2020.05.04
Ivy Generator  (0) 2020.01.21
V4[브이포] 원테이크 인게임 플레이 영상  (0) 2020.01.21

+ Recent posts