3dmax導入unity問題(1) 軸角度座標

3dmax用FBX格式把模型導出並導入unity時需要注意的問題。

目錄

二、軸心位置問題

2.1、一個物體

2.2、兩個物體

2.3 分部分導出

三、角度問題

3.1、問題研究

3.2、解決方案操作

四、旋轉操作

4.1、簡單旋轉情況

4.2、複雜旋轉情況

4.3、不同視圖創建的物體

4.4、小結

4.5、開門問題(研究過程,可以不用看,避免混亂)

4.5.1 (我的)創建門的過程:

4.5.2 【偏移:局部】

4.5.3 【偏移:世界】

4.5.4 開門結論

五、縮放操作

七、結論


3dmax和unity的座標單位

沒有修改單位的情況下,默認m爲單位。

放到Unity中,結果能夠和Unity裏面的(1,1,1)大小的Cube重合

把3dmax的單位改成mm,結果就是1000mm的立方體和Unity裏面1個單位的立方體是重合的。

說明Unity裏面的1個單位就是3dmax裏面的1m。

二、軸心位置問題

上面的問題也算是軸心的角度問題,這裏討論軸心位置問題。

2.1、一個物體

創建一個小球,座標設置成(0,0,0)

導入unity中,結果,座標也是(0,0,0)。

修改物體座標,再次導入unity中,物體有個初始座標了,拖出來到Hierarchy裏面,會有個座標在物體上,但是修改物體座標爲(0,0,0),模型能夠顯示在unity的原點位置,這種情況問題不大。

大部分模型拿來放到unity中也不是用它自己的初始化位置,而是會給他一個位置(無論手動添加到場景中還是代碼設置)。

-------------------------------------

接下來要修改軸的位置了。

在上面的基礎上,在unity中,創建一個子物體,座標是(0,0,0),這個子物體的位置就和3dmax導入的模型重合在一起的。

3dmax中修改軸的位置,移動到物體外面。

導入uinty,能看到軸心在小球物體外面了,而且P5這個對象有座標。

這個座標到底是什麼呢?

可以看到這個代表unity原點的點,在3dmax的小球的裏面,小球的位置是在(0,0,0)沒錯的,但是P5這個對象的座標則是(0,0,-6)的。

假如把P5的座標設置爲(0,0,0)的話,小球就不在(0,0,0)上了。

創建一個(0,0,0)相對座標的子物體,

子物體會出現在軸心位置

結論:一個物體,在unity裏面的座標值指的是軸心的座標。

注意,其實在unity裏面點擊物體看到的座標軸不一定就是模型的軸心,這裏是1個物體,情況簡單。

多個物體時,Unity會自動算一個軸心顯示的,一般是幾個模型的中心,這個顯示軸心不一定就是模型的軸心。而相對座標(0,0,0)的子物體則一定就是軸心的位置。

2.2、兩個物體

導入unity中

在unity中看到的和3dmax中一樣的。

假如我把Sphere001的座標從修改爲(0,0,0),改成(0,10,0)。

導入unity中也是一樣的

但是,這種情況其實是有問題的

用小球看不出來,假如我創建一個大樓。

隨便建,不用考慮大樓在世界座標中的位置。

導入unity後

大樓就偏了。

爲什麼說偏了呢?因爲軸心偏了。問題和前面一個物體是手動把軸心拖出來是一樣的。

這裏明明P6座標是(0,0,0),大樓就是不在(0,0,0),不在下面正方形(假設是廣場)的中心。

這個大樓不是整個世界,是一個大場景中的一部分,比如一個廣場上的某一座大樓。Unity中的整個場景不會是全部用一個max文件創建的,會有多個max文件,多個人員,創建一個世界中的不同部分,然後合併組織成一個完整的場景的。

比如大樓原本計劃在unity場景的(0,0,0)的,上面的導出模型的情況下,根本沒有方便的操作去把大樓模型放到(0,0,0)的,因爲它的軸心在模型的外面。

3dmax導出的模型的軸心必須在模型的中心,才能在場景組織時和其他模型能配合起來。

如何操作:3dmax中創建包含全部模型的頂層組,並把該組座標設置爲(0,0,0)。

unity中好使用了。

--------------------------------

這裏其實還有的小問題,大樓跑到地下去了。

在3dmax中把組的軸心拖到地板中心

進入unity中,則模型P8,拖動出來就有個初始座標了(0,-3.4,0)。

把座標改成(0,0,0),則:

所以我們要求的模型軸心有兩種:物體中心或者底面中心。

兩種都可以,設備一般要求物體中心,大樓等建築物體中心和地面中心都行,大樓等物體中心的情況下,代碼上也是能統一處理的。

---------------------------------------------------------------------

其實這裏就不是一定要把頂層組設置(0,0,0)了,和最前面的一個物體的情況一樣。大不了有個初始座標,使用是設置一下座標就好了。

沒有頂層組的情況下,3dmax導出的模型的軸心是原來3dmax中的世界座標的(0,0,0)的位置。有頂層組的情況下,頂層組作爲一個物體考慮,模型的軸心就是組的軸心,一般也就是組下面的模型的中心。

--------------------------------------------------------------------------------------------------------

2.3 分部分導出

我們項目一般是一個園區建模,拿到的模型需要將園區的地形和建築分別導出給我們,我們再在unity裏面搭建成完整的場景。

對於這種整體和部分的情況下的位置問題在這裏研究一下。

創建一個3dmax場景模擬一下。

【偏移:世界】旋轉90度,導入unity

座標從3dmax裏面的(100,200,300)變成了unity裏面的(-100,300,-200),這個先不管。

接下來把各個部分單獨導出。

有兩種方式

1.選擇子物體(分組)保存爲max文件,打開max文件再導出fbx。

打開導出的文件,發現會多一個園區。

2.選擇子物體(分組),導出子物體爲fbx。

結果來看,兩種方式都可以。看3dmax的分工合作方式。這塊我還不瞭解,作爲一個軟件開發人員。(如果我來分配建模工作,首先位置以地形爲主,先把地形建好,其他建築正確擺放到地形上,再導出。)

要注意的是,因爲前面導出fbx導出時先【“按遞歸方式打開”,選擇全部物體,旋轉軸】了,如果現在選擇一個組,導出選定對象或者保存選定對象時,只會導出這個組,組裏面的東西都沒有。這個還挺不習慣的。

需要做的操作是先關閉組,再打開組,這樣子選擇的子物體(組)時,其實就是把子物體(組)裏面的物體也都包括了。

//todo:其實按我設想,應該可以二次開發,做個自動將頂級組(如:園區)下面的一級子組(如:地形等)自動導出成fbx的工具。

-------------------------------------------------------

本來想說可能導出後部分的座標可能有問題,所以這部分放在這裏。但拖到unity裏面,能保持建築在正確的位置上的。

不過能注意到,每個子物體多了一層。其實這點從前面的子物體的max文件也能看到的,明明選擇導出的是地形,結果保存的max打開裏面多了個園區。

正確操作是,這種情況下,不要頂級分組了,就只有各個部分的分組(這樣也不要做前面提到的打開操作了,不過有”按遞歸方式打開“的話,還是要先關閉了)。

各個分組導選定對象,並導入unity。

三、角度問題

參考:【3dsmax】導入Unity3D需要注意的軸問題

3.1、問題研究

先創建一個Demo場景,能辨認出朝向的。

放入unity裏面結果

模型對象角度是(0,0,0)的,子物體對象角度是(-90,0,0)的,不行。

需要注意的是,前面導出的高級設置軸轉換,無論是Y向上還是Z向上結果是一樣的。

------------------------------------------

加個頂級分組再導出

這種情況就變成模型對象(根對象)是(-90,0,0),子物體是(0,0,0)了。

多加幾層分組也是一樣的:

1.在沒有頂級分組的情況下,導入Unity中,根物體的角度是(0,0,0),第一級子物體(或分組)的角度是(-90,0,0),後續子物體(或分組)的角度是(0,0,0)

2.在有頂級分組的情況下,根物體角度是(-90,0,0),下面的子物體角度都是(0,0,0)

3.2、解決方案操作

旋轉軸:在3dmax中選中物體,切換到層次,僅影響軸。

在沒有頂級分組情況下:

紅色的軸是X軸,綠色的是Y軸,藍色的是Z軸,默認是Z軸向上的。

進入旋轉操作,注意要選中角度捕捉,設置90度。

旋轉90°

注意,這時雖然看起來全選了,實際上選擇就只有頂級的4個分組和物體,旋轉的也是這4個的軸。導入Unity中,後上面的4個對於與第2級物體了,是(0,0,0)的,而第3級變成了(-90,0,0),4級則還是(0,0,0)了。

就算按ctr+a,或者全部框選,看起來像選中所有的物體,旋轉所有物體的軸。

再導出FBX導入Unity,發現還是有些是(-90,0,0)。

正確操作是,先全選,然後選擇按遞歸方式打開,然後再全選(這樣才能選中全部物體),再旋轉軸。

導出到Unity中後,所有的層級的物體都是(0,0,0)了。

---------------------------------------------------------------------------

在有頂級分組的情況下,假如旋轉頂級分組本身的軸,導入Unity中則會是2級物體是(-90,0,0),其他都是(0,0,0)

正確操作還是和上面一樣,要選擇按遞歸方式打開,再旋轉全部軸。

四、旋轉操作

4.1、簡單旋轉情況

繞z軸(向上)旋轉:

 

繞y軸旋轉

旋轉物體時,軸也是一起旋轉的(這裏有先把軸居中了)

在3dmax裏面是沿着y軸旋轉30度,到unity裏面就變成了(-60,-90,90)。

假如這時按導出FBX要旋轉軸90度的操作,因爲按全面的教程操作是會把全部旋轉的。但是有個問題,旋轉的參考座標系,默認是世界,這時的旋轉的圈和軸方向就不一致了。

沿着世界座標的x軸,旋轉90度,結果在unity裏面角度就是(0,-30,0)了。

把角度改成(0,0,0)的話,水平方向轉了一下,垂直方向的角度還是斜的。

也就是說這時,這種傾斜的狀態就是物體的原始角度(0,0,0)狀態了。

參考座標系改爲局部(只有這個座標系旋轉控制的圈是和物體的軸方向一致的),沿局部座標x軸旋轉90度,導出後坐標是(0,0,30)。

這時把角度改成(0,0,0)物體就回正了。

從邏輯上講,這種狀態更符合直觀邏輯。

4.2、複雜旋轉情況

沿y軸旋轉10度

沿z軸旋轉20度

沿x軸旋轉30度

結果:

還是和上面一樣的,“局部”座標系,旋轉90度,導出fbx。到unity裏面。

把Box001的角度調整爲(0,0,0),就又回正了。

4.3、不同視圖創建的物體

3dmax還有個問題,在不同視圖下創建的物體的軸方向(“局部”座標系下)是不同的。

發現:

1.頂、前、左創建的物體,在對應視圖下都是x軸向右,y軸向上,z軸向裏。

2.正交和頂視圖創建的物體的軸方向一致。

(成頂級組+局部軸旋轉後)導出到unity裏面,正交和頂角度是(0,0,0),前和左各有角度。

這裏說明一下爲什麼要注意物體的角度,或者說是物體的軸的角度。

模型提供給unity後,不是靜止的,在unity中會用腳本對物體進行操作,比如向某個方向移動,如向上移動。

假如角度不一致,用相同的腳本,實現的效果就會很怪。

public class Move : MonoBehaviour
{
    //private Vector3 speed=new Vector3(0,1,0);

    // Update is called once per frame
    void Update()
    {
        Vector3 speed = new Vector3(0, 1, 0);
        transform.Translate(speed);//正交和頂視圖向上移動,前和左向左移動。
        //transform.localPosition += transform.up;//正交和頂視圖向上移動,前和左向左移動。
        //transform.localPosition += speed;//全部物體朝上移動
    }
}

public class Rotate : MonoBehaviour
{
    void Update()
    {
        Vector3 speed = new Vector3(0, 1, 0);
        transform.Rotate(speed);//正交和頂視圖一起旋轉,前和左向一起旋轉。
        //transform.localEulerAngles += transform.up;//正交和頂視圖一起旋轉,前和左向各自旋轉。
        //transform.localEulerAngles += speed;//全部物體一起旋轉
    }
}

對於前面這種簡單方向移動的情況,在3dmax中把所有物體的軸改成(90,0,0),導入unity中,所有物體的軸方向就一致,都是(0,0,0)了。

注意這裏的座標系是“世界”了,如果選局部的話,沒個物體的絕對角度都是(0,0,0)了。

4.4、小結

參考:3dmax參考座標系怎麼設置

發現我們建模人員沒有改過參考座標系的設置,從頭到尾都是用”視圖“。視圖一定程度上相當於”世界“了。

結合前面的,導出fbx,旋轉軸有3種操作:

4.4.1、”世界“座標系,軸角度【絕對:世界】設置爲(90,0,0)。

導入到unity後所有物體的角度就都是(0,0,0)。

4.4.2、"世界"座標系,軸角度【偏移:世界】設置爲(90,0,0),這個和手動繞x軸旋轉90度的操作是一樣的。

導入unity後,物體的角度會發生變化,參考前面的【4.1】部分的情況。

4.4.3、“局部"座標系,x軸偏移旋轉90度(或者手動繞x軸旋轉90度),導入unity後,物體角度保存3dmax中的角度。

這種情況下的旋轉軸90度操作只是爲了消除3dmax導入unity造成的(-90,0,0)角度的偏移,物體本身還是有角度的。

參考前面的【4.1】部分的情況。

對於

 

4.5、開門問題(研究過程,可以不用看,避免混亂)

對於門這種模型,特別是雙開門,兩個門板在創建時會有可能用了對稱的方式複製出來,這樣的話,它們的軸也是對稱的。

4.5.1 (我的)創建門的過程:

1.在透視視圖創建一個長方體A。

2.修改長方體的軸,移動並對其到一邊的中心。要開啓軸約束

3.鏡像一個長方體B,複製方式

4.將B和A對其

5.另外創建一個門框

6.創建其他東西,並分組

4.5.2 【偏移:局部】

採用【4.4.3】局部座標系偏移旋轉90度的方式,結果很奇怪

旋轉過程中,發現通過鏡像方式創建出來的物體在[僅影響軸]的狀態下跟着軸一起旋轉了:

這個說實話,很奇怪,非常奇怪。

鏡像自身,不復制,也是會變成旋轉軸旋轉物體。

 

我原本是想推薦“【偏移:局部】“的方式旋轉的,因爲通過【絕對:世界】方式設置軸角度,會導致在unity中所有的軸都是(0,0,0),那樣的話門的軸就不對稱了。具體看下面的4.5.2。

本來打算先不用鏡像的操作,手動複製一個物體並旋轉物體和軸的方式,使兩個門的軸對稱。

居然做不到!

這裏的軸對稱是指

用幾何體方式鏡像出來的物體不會出現旋轉軸旋轉問題的問題

問題是這樣鏡像出來的東西軸不對稱,保存和原來的物體的軸一樣的角度

4.5.3 【偏移:世界】

在4.5.1的過程創建的模型的基礎上用"偏移:世界"([4.4.2])的方式旋轉(90,0,0)度

旋轉後

導入unity後DoorLeft是(0,0,0),DoorRight是(-180,0,0)

給Door1添加開門腳本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DoorOpen : MonoBehaviour
{
    public Vector3 speed = new Vector3(0, 1, 0);
    public Space space = Space.Self;
    public Transform Left;
    public Transform Right;
    void Start()
    {
        if (Left == null)
        {
            Left = transform.Find("DoorLeft");
            
        }
        if(Left)
        print("left:" + Left.up);

        if (Right == null)
        {
            Right = transform.Find("DoorRight");
        }
        if (Right)
            print("right:" + Right.up);
    }

    void Update()
    {
        
        //transform.Translate(transform.forward);
        if(Left)
            Left.Rotate(speed, space);
        if(Right)
            Right.Rotate(speed, space);//默認就是Space.Self

        //Left.Translate(speed,Space.World);
        //Right.Translate(speed, Space.World);
    }
}

speed是(0,1,0),其實也是旋轉角度,space是Self。

效果:

再改一下,左側相對完整的一個開門腳本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DoorOpen : MonoBehaviour
{
    public Vector3 speed = new Vector3(0, 1, 0);
    public Space space = Space.Self;
    public Transform Left;
    public Transform Right;
    public float angleMax = 90;
    void Start()
    {
        if (Left == null)
        {
            Left = transform.Find("DoorLeft");
            
        }
        if(Left)
        print("left:" + Left.up);

        if (Right == null)
        {
            Right = transform.Find("DoorRight");
        }
        if (Right)
            print("right:" + Right.up);
    }

    private int direction = 1;

    public bool loop = true;

    public bool isMove = true;

    public Vector3 currentAngle;

    void Update()
    {
        if (isMove == false) return;
        currentAngle += speed * direction;//因爲左邊是0->90,右邊是180->90;需要另外記錄一下旋轉角度
        if (Left)
        {
            Left.Rotate(speed * direction, space);
        }
        if (Right)
        {
            Right.Rotate(speed * direction, space); //默認就是Space.Self
        }
        if (currentAngle.y > angleMax || currentAngle.y < 0)
        {
            if (loop)
            {
                direction *= -1; //旋轉一下角度
            }
            else
            {
                isMove = false;//停止運行
            }
        }
    }
}

效果:

4.5.4 開門結論

用【偏移:世界】方式旋轉軸導出的門模型,可以用腳本方便的製作開門動畫。有些建模人員可能從來就沒操作過局部視圖,導出前的旋轉使用默認的”視圖“參考座標系就好了。

五、縮放操作

對於縮放操作,簡單的一個物體,縮放爲200%,導出到unity裏面後就是(2,2,2)了

之所以需要導出給unity的模型不要有縮放比例,即Scale要爲(1,1,1),是因爲在Unity裏面會對模型進行一下操作。

雖然我們在計算一個物體的大小時是有考慮Scale參數的,但是還有其他子物體的操作情況,總之,設置爲(1,1,1)是最保險的。

現在的問題是在3dmax裏面有縮放需求的情況下,如何導入unity後Scale爲(1,1,1)。

1.附加

附加到一個沒有縮放的物體上。

物體A比例是200%,物體B比例是100%。

選擇物體B,轉換成可編輯多邊形,點擊附加,選中物體A,結果A就不見了,合併到物體B裏面了。

同時物體B的軸、比例都不變,合併後的物體以B爲準,A的200%的縮放也就不存在了。

附加後物體A就不存在的,對於需要操作物體A的情況來說,可能不大方便。

因爲最終實際的模型是A,B只是爲了消除縮放的影響,B物體可以是一個半徑爲0的球,且居中到物體A的中心,通過對齊方式。

2.加組

給有縮放的一個或者相關的多個物體加上組,結果組上面的縮放則是100%。

物體上的縮放是不變,不過這種情況下一般也就操作組,物體僅僅是作爲一個子部件存在了。

3.縮放子元素

通過轉換成可編輯多邊形,選中所有點,縮放點的方向來改變物體的大小。

修改點後物體的比例還是100%的。

發現,簡單的整體模型,Box,無論用點線面縮放都行的。

但是需要注意的是像茶壺這種的有多個部分組成的模型,如果不是用點縮放,用線、面等縮放,各個部分會獨立縮放,導致整體就怪怪的了。

而用點縮放,則結果正常。

旋轉操作也可以通過這幾種方式消除對角度的影響

七、結論

1.Unity裏面的1個單位就是3dmax裏面的1m。

2.max文件導出前文件中必須有一個頂層組,有且只有一個。

3.必須選擇“按遞歸方式打開”,再旋轉“全部”模型的軸的角度,旋轉成Y軸(綠色)向上,注意這時的參考座標系爲視圖或者世界(默認就是視圖的)。

4.整個園區的各個部分的導出時不需要頂級組,只需要選中各個部分,並導出選中物體就行(參考前面2.3)。

    備註:老版本(2012)的3dmax沒有“按遞歸方式打開”,則必須升級max版本,因爲人工打開的話,很容易出錯,工作量也大。

 

鑑於導出fbx給unity前需要做這些操作,而後續可能還需要在原來基礎上編輯修改模型。可以在改完模型的分組,建立頂級分組後,旋轉軸之前,另存爲一個專門用於導出fbx的max文件。在該max文件中做修改並導出爲FBX文件,導出後這個文件就沒用了。修改模型還是原來的文件,每次導出fbx都要再做一次旋轉軸操作。

不將旋轉軸的操作放到另一個max文件中的話,可能會導致軸混亂,比如,在旋轉好軸的模型的基礎上,再添加其他模型,新的模型的軸和前面的模型的方向就不一致了。下次導出fbx時必須人工區分開來兩種軸的物體。

//todo:這些操作(組、遞歸打開、旋轉軸、導出選定對象)用二次開發方式自動實現

 

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