unity3d 导出 服务器

2018-11-30 11:43:46 hulai168 阅读数 1058
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

                                                 Layaair 3D资源加载
 

layaair 预加载3D资源(Unity3D 导出资源)  和  2D 资源还是有些区别的。

2D资源的预加载 https://blog.csdn.net/nicepainkiller/article/details/82971636

这个就是我们加载  U3D 导出的 资源文件

基本就这块

 

 

// 程序入口
class GameMain {
    constructor() {
 
 
       //let  screenRatioFitter :ScreenRatioFitter = new   ScreenRatioFitter();
       //Laya3D.init(screenRatioFitter.Width,screenRatioFitter.Height, true);
 
 
        //初始化引擎
        Laya3D.init(SetupConfig.widthDesign,SetupConfig.heightDesign, true);
 
 
        //适配模式
        //Laya.stage.bgColor   = "#000000";
        Laya.stage.scaleMode = Laya.Stage.SCALE_NOBORDER; 
        //Laya.stage.scaleMode = Laya.Stage.SCALE_EXACTFIT;
        Laya.stage.alignH    = Laya.Stage.ALIGN_CENTER;
        Laya.stage.alignV    = Laya.Stage.ALIGN_MIDDLE;
        Laya.stage.screenMode= Laya.Stage.SCREEN_VERTICAL;
 
        //开启统计信息
        Laya.Stat.show();
 
        // //添加3D场景
        // var scene: Laya.Scene = Laya.stage.addChild(new Laya.Scene()) as Laya.Scene;
 
        // //添加照相机
        // var camera: Laya.Camera = (scene.addChild(new Laya.Camera(0, 0.1, 100))) as Laya.Camera;
        // camera.transform.translate(new Laya.Vector3(0, 3, 3));
        // camera.transform.rotate(new Laya.Vector3(-30, 0, 0), true, false);
        // camera.clearColor = null;
 
        // //添加方向光
        // var directionLight: Laya.DirectionLight = scene.addChild(new Laya.DirectionLight()) as Laya.DirectionLight;
        // directionLight.color = new Laya.Vector3(0.6, 0.6, 0.6);
        // directionLight.direction = new Laya.Vector3(1, -1, 0);
 
        // // //添加自定义模型
        // // var box: Laya.MeshSprite3D = scene.addChild(new Laya.MeshSprite3D(new Laya.BoxMesh(1, 1, 1))) as Laya.MeshSprite3D;
        // // box.transform.rotate(new Laya.Vector3(0, 45, 0), false, false);
        // // var material: Laya.StandardMaterial = new Laya.StandardMaterial();
        // // material.diffuseTexture = Laya.Texture2D.load("res/layabox.png");
        // // box.meshRender.material = material;
 
        // let fish :Laya.Sprite3D = Laya.Sprite3D.load("res/fishPrefab/Fish0/Laya.lh");
      
        // scene.addChild(fish);
        // fish.transform.translate ( new Laya.Vector3(10000,0, 1000000)); 
 
  
 
        // let scene: Laya.Scene=  Laya.Scene.load("res/LayaScene_Person/Person.ls");
 
        // Laya.stage.addChild(scene);
        // //创建摄像机(横纵比,近距裁剪,远距裁剪)
        // var camera: Laya.Camera = new Laya.Camera(0, 0.1, 1000);
        // //加载到场景
        // scene.addChild(camera);
        // //移动摄像机位置
        // camera.transform.position = new Laya.Vector3(0, 0, -10);
        // //旋转摄像机角度
        // camera.transform.rotate(new Laya.Vector3(0, 0, 0), true, false);
        // //设置摄像机视野范围(角度)
        // camera.fieldOfView = 35;
        // //设置背景颜色
        // camera.clearColor = new Laya.Vector4(0, 0, 0.6, 1);
        // //加入摄像机移动控制脚本
 
        // //创建方向光 -------------------
        // var light: Laya.DirectionLight = scene.addChild(new Laya.DirectionLight()) as Laya.DirectionLight;
        // //移动灯光位置
        // light.transform.translate(new Laya.Vector3(0, 2, 5));
        // //调整灯光方向
        // light.transform.worldMatrix.setForward(new Laya.Vector3(0, -0.5, 0));
        // //设置灯光环境色
        // light.color = new Laya.Vector3(1, 1, 1);
 
 
        // Laya.timer.loop(100,this,()=>
        // {
        //     // scene.transform.rotate(new Laya.Vector3(0, 0, 0), true, false);     
        // });
 
 
 
        let scene:Laya.Scene = new  Laya.Scene();
        Laya.stage.addChild(scene);
 
 
        let camera:Laya.Camera = new Laya.Camera();
        scene.addChild(camera);
 
 
        let box: Laya.MeshSprite3D = scene.addChild(new Laya.MeshSprite3D(new Laya.BoxMesh(2, 2, 2))) as Laya.MeshSprite3D;
        //let material: Laya.StandardMaterial = new Laya.StandardMaterial();
        //material.diffuseTexture = Laya.Texture2D.load("res/layabox.png");
        //box.meshRender.material = material;
 
        let build:Laya.Sprite3D = Laya.Sprite3D.load("res/fishPrefab/Fish0/Laya.lh");
        box.addChild(build);    
 
        box.transform.localPosition = new Laya.Vector3(0,0,-100);
        scene.addChild(box);
 
         
 
        // ///需要加载的资源列表   
        // let resArray : Array<any> = [
        //     { url:"res/background/back.jpg",            type:Laya.Loader.IMAGE },
        //     { url:"res/atlas/button.atlas",             type:Laya.Loader.ATLAS },
        // ];
 
        // Laya.loader.load( resArray, Laya.Handler.create(this, this.onCompelt), Laya.Handler.create(this, this.onprogress) );
 
     
 
        
        ///需要加载的3D资源列表   
        let res3DArray : Array<any> = [
            { url:"res/fishPrefab/Fish0/Laya.lh",            type:Laya.Sprite3D },
            { url:"res/fishPrefab/Fish1/Laya.lh",            type:Laya.Sprite3D },
            { url:"res/fishPrefab/Fish2/Laya.lh",            type:Laya.Sprite3D },
            { url:"res/fishPrefab/Fish3/Laya.lh",            type:Laya.Sprite3D },
            { url:"res/fishPrefab/Fish4/Laya.lh",            type:Laya.Sprite3D },
            { url:"res/fishPrefab/Fish5/Laya.lh",            type:Laya.Sprite3D },
            { url:"res/fishPrefab/Fish6/Laya.lh",            type:Laya.Sprite3D },
        ];
 
     
        Laya.loader.create(res3DArray, Laya.Handler.create(this,()=>
        {
            console.log("加载3D完成");
 
            for(let i = 0; i < res3DArray.length; i++)
            {
                   let box: Laya.MeshSprite3D = scene.addChild(new Laya.MeshSprite3D(new Laya.BoxMesh(2, 2, 2))) as Laya.MeshSprite3D;
                   let build:Laya.Sprite3D    = Laya.Sprite3D.load(res3DArray[i].url);
                   box.addChild(build);  
                   scene.addChild(box);
 
                   box.transform.localPosition = new Laya.Vector3(0,10*i,-100);
            }
 
            //预加载完成后  有两种方式 获得资源
            ////////////////////////////////////////////////////////////
            ///第一种是  
           let build:Laya.Sprite3D   =  Laya.Sprite3D.load("res/fishPrefab/Fish2/Laya.lh");
 
           ///第二种是
           let build2:Laya.Sprite3D  =  Laya.loader.getRes("res/fishPrefab/Fish2/Laya.lh");//这个函数 是2d 还是 u3d 通用的接口, 返回资源类型是根据资源的类型来的
 
 
        }),
        Laya.Handler.create(this, (pro)=>
        {
            console.log("加载3D进度:"+pro);
        }));
 
 
 
 
 
    }
 
        //加载完成
    private onCompelt():void   
    {
        //UIManager.getInstance();
    }
     //加载进度
    private onprogress(pro:number):void
    {
        console.log("加载进度:"+pro);
    }
      
}
new GameMain();
--------------------- 
作者:nicepainkiller 
来源:CSDN 
原文:https://blog.csdn.net/nicepainkiller/article/details/83994540 
版权声明:本文为博主原创文章,转载请附上博文链接!

2018-02-27 16:58:00 mango9126 阅读数 4846
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

前言:

    这篇文档写了很久了,今天有群里朋友询问,干脆贴出来一起学习下吧。

一、在服务器中使用Recast Navigation进行导航的时候,可以使用Unity场景中的NavMesh信息,导出静态导航网格,提供给客户端或者服务器使用。

二、借助CritterAI插件,在Unity中生成.navmesh静态导航文件。CritterAI下载地址

1. 解压unity3d_nav_critterai-master.zip文件,在项目中,把unity3d_nav_critterai文件夹下相应Unity版本中的Assets放入到Unity3d项目中的Assets文件夹下。


2. 此时的Unity3d的编辑器中会出现CritterAI

点击CritterAI->Create NMGen Assets->Navmesh Build : Standard进行初始化CAI文件,

 

初始化完成后,项目目录中将出现几个文件:

CAIBakedNavmesh.asset

MeshCompiler.asset

NavmeshBuild.asset

如下图所示:

        

3. 如果使用Terrain来做地图导航,场景中新建Terrain,目录中就存在一个对应的New Terrain.asset资源文件,

 

添加一个能生成寻路网格的编辑器CritterAI->Create NMGen Assets->Compiler : Terrain(该目录下有多个编辑器,可以根据场景地图的需求进行选择,常用的为TerrainMeshCompilerMeshCompiler默认的有,表示添加当前场景中存在MeshFilter组件的物体进入导航系统中)

然后,把我们创建的Terrain的资源文件New Terrain.asset绑定到TerrainCompiler上。

 

4. NavMeshBuild中设置Build的参数,在Input Configuration中点击Add添加新建的TerrainCompiler作为Processors的列表成员。

Build参数类似Unity3dBake时候的参数,下图中的参数,是官网中生成navmesh文件的参数。具体详细设置可以参考官网文档http://www.critterai.org/projects/cainav/doc/

 

最后点击BuileBake,开始将当前Processors列表中加入的所有成员,包括CompilerFilter生成navmesh文件

5. BuildBake后,选中CAIBakeNavMesh,点击Save,导出为navmesh文件,此时会生成两个相应的文件,例如xinshoucun.navmeshsrv_xinshoucun.navmesh,其中srv_开头的文件用于服务端寻路,另一个是用于客户端使用该插件寻路。我们在服务器使用的为srv_xinshoucun.navmesh文件。

  

6. 至此,navmesh文件生成,如果是在场景中,除了MeshFilterTerrain,有其他的实体需要在导航的过程中参与,可以使用ComponentFilter来做

例如:在使用Component FilterTag后,项目中会出现TagInputFilter,选中之后,在Tags下,可以选择当前场景中所有的GameObject或者Prefabs的标签,选定指定的标签。

 

在加入了Filter后,在NavMeshBuild的时候,要在Processors列表中加入TagInputFilter,再执行以上的BuildBake的操作,即可将该标签下的物体加入导航系统中。

 

7. 如果是用客户端寻路,在生成完毕后,建议删除Unity3d项目中Assets\Plugins下关于CAINav的文件,否则启动游戏可能会造成无法导出游戏的错误,原因未知,官网中没有说明。我们使用服务器导航,可以忽略此步骤。

下一篇:客户端导出NavMesh信息后,服务器的使用
2015-12-04 18:32:54 jq0123 阅读数 5401
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

Unity3d导出场景地图寻路

(金庆的专栏)

Unity3d中用无渲染的透明盒子摆出地面和阻档区域。
        this.renderer.enabled = false;
所有这些盒子设为Navigation Static.
阻档盒子Navigation Layer设为 Not Walkable.
用EditorObjExporter.cs 导出这些盒子到obj文件。

http://wiki.unity3d.com/index.php?title=ObjExporter





用Recast Demo 打开obj文件,就可以测试地图寻路了。




2016-06-17 12:15:11 fansongy 阅读数 12283
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。


文章作者:松阳

本文出自 阿修罗道,禁止用于商业用途,转载请注明出处。  

原文链接:http://blog.csdn.net/fansongy/article/details/51699058







有时我们会需要Unity3d的地图信息,比如A*之类的逻辑运算。当这些操作要放到服务器上进行时,就需要地图信息。通常项目中的行走区域是使用Navmesh制作的。这篇文章中,介绍如何将Navmesh的信息导出成bitmap。

脚本效果

整个工具的设置界面放到Inspector中,由于是程序同学用,所以界面就比较糙,对付用吧 可以设置几个数值,导出地图的左顶点坐标、地图精度、宽、高,设置界面如下图所示:


设置好后点击Export按钮,即可在场景中计算出可行走区域:


可以看到,与Navmesh的可行走区域相对应位置会画出绿色标尺线,不能行走则标为红色。最终导出的信息内容如下:

startpos=(-6.0, 0.0, 6.0)
height=15
wide=15
accuracy=1
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},
{0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,},
{0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,},
{0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,},
{0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,},
{0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,},
{0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,},
{0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,},
{0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,},
{0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},

核心原理

使用一个Unity3d中Navmesh的接口:

NavMesh.SamplePosition

来检测一个点是否在可行走区域中。同时将内容输出到日志中。检测时增加了不同高度的采样,防止由于斜坡引起的遗漏。

代码实现

using UnityEngine;
using System.Collections;
using System.Text;
using UnityEditor;

public class NavExport : MonoBehaviour
{
    #region Public Attributes
    public Vector3 leftUpStart = Vector3.zero;
    public float accuracy = 1;
    public int height = 30;
    public int wide = 30;
    #endregion

    #region Unity Messages

    void OnGUI()
    {
        if (GUILayout.Button("Export"))
        {
            exportPoint(leftUpStart, height, wide, accuracy);
        }
    }

    #endregion

    #region Public Methods

    public void Exp()
    {
        exportPoint(leftUpStart, wide, height, accuracy);
    }

    public void exportPoint(Vector3 startPos, int x, int y, float accuracy)
    {
        StringBuilder str = new StringBuilder();
        int[,] list = new int[x, y];
        str.Append("startpos=").Append(startPos).Append("\r\n");
        str.Append("height=").Append(y).Append("\r\nwide=").Append(x).Append("\r\naccuracy=").Append(accuracy).Append("\r\n");
        for (int i = 0; i < y; ++i)
        {
            str.Append("{");
            for (int j = 0; j < x; ++j)
            {
                int res = list[j, i];
                NavMeshHit hit;
                for (int k = -10; k < 30; ++k)
                {
                    if (NavMesh.SamplePosition(startPos + new Vector3(j * accuracy, k, -i * accuracy), out hit, 0.2f, NavMesh.AllAreas))
                    {
                        res = 1;
                        break;
                    }
                }
                Debug.DrawRay(startPos + new Vector3(j * accuracy, 0, -i * accuracy), Vector3.up, res == 1 ? Color.green : Color.red, 5);
                str.Append(res).Append(",");
            }
            str.Append("},\n");
        }
        Debug.Log(str.ToString());
    }
    #endregion

}

[CustomEditor(typeof(NavExport))]
public class NavExportHelper : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        if (GUILayout.Button("Export"))
        {
            var exp = target as NavExport;
            exp.Exp();
        }
    }
}

如果你觉得这篇文章对你有帮助,可以顺手点个,不但不会喜当爹,还能让更多人能看到它... 

2016-09-26 18:15:11 cp790621656 阅读数 11509
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

这个项目的客户端使用Unity 自带的 NavMesh 来做寻路。然后怪物的刷新以及移动是由服务器负责的,但是这样会有一个问题,如果怪物在场景边缘或者怪物与人之间有障碍物,服务器是又不知道这里有障碍物,那怪物的移动就没法做了。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn  转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn  转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn  转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn  转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn  转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

所以有这么个需求,让服务器能够判定当前移动位置是否在可行走区域之内。

所以就需要把客户端的 NavMesh数据导出给服务器使用(或许有其它的办法)。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn  转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn


转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

Unity 提供了相关的接口:

NavMesh.CalculateTriangulation

利用这个接口能够获取到NavMesh 的数据,顶点以及顶点索引。

熟悉GL或DX的童鞋知道有了顶点以及顶点索引就可以画出模型来。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

下面是我写的一个简单的示例,用来把NavMesh 数据导出到一个 obj 文件,obj 是一种文本形式存储的模型文件格式。导出之后直接拖到Unity 中可以看到NavMesh 的形状。

/************************************************
 * 文件名:ExportNavMesh.cs
 * 描述:导出NavMesh数据给服务器使用
 * 创建人:陈鹏
 * 创建日期:20160926
 * http://blog.csdn.net/huutu/article/details/52672505
 * ************************************************/

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
using UnityEngine.SceneManagement;

public class ExportNavMesh
{
    [MenuItem("NavMesh/Export")]
    static void Export()
    {
        Debug.Log("ExportNavMesh");

        NavMeshTriangulation tmpNavMeshTriangulation = NavMesh.CalculateTriangulation();

        //新建文件
        string tmpPath = Application.dataPath + "/" + SceneManager.GetActiveScene().name + ".obj";
        StreamWriter tmpStreamWriter = new StreamWriter(tmpPath);

        //顶点
        for (int i=0;i<tmpNavMeshTriangulation.vertices.Length;i++)
        {
            tmpStreamWriter.WriteLine("v  "+ tmpNavMeshTriangulation.vertices[i].x+" "+ tmpNavMeshTriangulation.vertices[i].y+" "+ tmpNavMeshTriangulation.vertices[i].z);
        }

        tmpStreamWriter.WriteLine("g pPlane1");

        //索引
        for (int i = 0; i < tmpNavMeshTriangulation.indices.Length;)
        {
            tmpStreamWriter.WriteLine("f " + (tmpNavMeshTriangulation.indices[i]+1) + " " + (tmpNavMeshTriangulation.indices[i+1]+1) + " " + (tmpNavMeshTriangulation.indices[i+2]+1));
            i = i + 3;
        }

        tmpStreamWriter.Flush();
        tmpStreamWriter.Close();

        Debug.Log("ExportNavMesh Success");
    }
}

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

点击Export 导出后,会生成以 当前 Scene 命名的 obj 文件

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

拖到Unity 中绘制出来如下,证明我们成功导出了NavMesh的数据

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

把这个 obj 扔给服务器,服务器进行怪物是否在三角形 范围内判定。具体怎么做我不管了。