2019-12-18 23:39:32 sinat_25415095 阅读数 10

今天对比了three.js创建的场景和unity3d发布到webgl的场景下,发现还是unity3d渲染得好一些,但是相对three.js来说帧率会降低。
发布webgl遇到的一点知识,难得以后又去到处查,这里记录一下。

1 unity3d发布webgl时去默认的unity logo和加载进度条

见这篇文章。

2 安装配置IIS

第一步安装和部署IIS:
IIS的安装和配置见这篇文章。
第二步设置IIS中的MIME类型:
见这篇文章。

Todo: 先大概记录一下,这周末来个全套流程吧,也方便对IIS和js不熟悉的同学,顺带安利一波小站

2014-10-17 17:43:48 book_longssl 阅读数 710



初学者经常把Awake和Start混淆。


简单说明一下,Awake在MonoBehavior创建后就立刻调用,Start将在MonoBehavior创建后在该帧Update之前,在该Monobehavior.enabled == true的情况下执行。




void Awake (){
}     
//初始化函数,在游戏开始时系统自动调用。一般用来创建变量之类的东西。

void Start(){
}
//初始化函数,在所有Awake函数运行完之后(一般是这样,但不一定),在所有Update函数前系统自动条用。一般用来给变量赋值。
我们通常书写的脚本,并不会定义[ExecuteInEditMode]这个Attribute,所以Awake和Start都只有在Runtime中才会执行


例1:


public class Test : MonoBehaviour {
    void Awake () {
        Debug.Log("Awake");
        enabled = false;
    }

    void Start () {
        Debug.Log("Start");
    }
}
以上代码,在Awake中我们调用了enabled = false; 禁止了这个MonoBehavior的update。由于Start, Update, PostUpdate等属于runtime行为的一部分,这段代码将使Start不会被调用到。


在游戏过程中,若有另外一组代码有如下调用:




Test test = go.GetComponent<Test>();
test.enabled = true;
这个时候,若该MonoBehavior之前并没有触发过Start函数,将会在这段代码执行后触发。




例2:


player.cs


private Transform handAnchor = null;
void Awake () { handAnchor = transform.Find("hand_anchor"); }
// void Start () { handAnchor = transform.Find("hand_anchor"); }
void GetWeapon ( GameObject go ) {
    if ( handAnchor == null ) {
        Debug.LogError("handAnchor is null");
        return;
    }
    go.transform.parent = handAnchor;
}


other.cs


GameObject go = new GameObject("player");
player pl = go.AddComponent<player>(); // Awake invoke right after this!
pl.GetWeapon(weaponGO);
...
以上代码中,我们在player Awake的时候去为handAnchor赋值。如果我们将这步操作放在Start里,那么在other.cs中,当执行GetWeapon的时候就会出现handAnchor是null reference.


总结:我们尽量将其他Object的reference设置等事情放在Awake处理。然后将这些reference的Object的赋值设置放在Start()中来完成。
当MonoBehavior有定义[ExecuteInEditMode]时


当我们为MonoBehavior定义了[ExecuteInEditMode]后,我们还需要关心Awake和Start在编辑器中的执行状况。


当该MonoBehavior在编辑器中被赋于给GameObject的时候,Awake, Start 将被执行。
当Play按钮被按下游戏开始以后,Awake, Start 将被执行。
当Play按钮停止后,Awake, Start将再次被执行。
当在编辑器中打开包含有该MonoBehavior的场景的时候,Awake, Start将被执行。


值得注意的是,不要用这种方式来设定一些临时变量的存储(private, protected)。因为一旦我们触发Unity3D的代码编译,这些变量所存储的内容将被清为默认值。


下面再来看看Unity圣典中的解释。


Awake()


当一个脚本实例被载入时Awake被调用。


Awake用于在游戏开始之前初始化变量或游戏状态。在脚本整个生命周期内它仅被调用一次.Awake在所有对象被初始化之后调用,所以你可以安全的与其他对象对话或用诸如 


GameObject.FindWithTag 这样的函数搜索它们。每个游戏物体上的Awke以随机的顺序被调用。因此,你应该用Awake来设置脚本间的引用,并用Start来传递信息。Awake总是在Start之前被调


用。它不能用来执行协同程序。
Start()


Start仅在Update函数第一次被调用前调用。Start在behaviour的生命周期中只被调用一次。它和Awake的不同是Start只在脚本实例被启用时调用。
你可以按需调整延迟初始化代码。Awake总是在Start之前执行。这允许你协调初始化顺序。


2015-04-25 14:09:49 yxriyin 阅读数 805

       有了上一个专题的经验,我决定通过和盗梦英雄对比来测试消耗性能的点。

       面板上的已经处理了,但战斗中确实还是差了10帧左右的感觉。而且我们的卡顿比他们明显很多。

       盗梦英雄:

       空闲阶段:47-58帧。

       战斗阶段:40-55帧

       大招阶段:25-50帧

       我们的游戏:

          空闲阶段:47-53帧。

        战斗阶段:30-45帧

       大招阶段:卡顿明显


       首先将场景去掉。对比帧数:

         空闲阶段:40-45帧。

        战斗阶段:30-40帧

       大招阶段:卡顿明显

        这么看来 场景引起的渲染影响也不算很大。那么就奇怪了。是UI问题更多么?

       有了上次的经验,让我对UI的的性能不是非常信任。即使屏蔽主城,UI单独渲染也只能到达40+帧的级别。

       没有UI:

       空闲阶段:45-50帧。

        战斗阶段:40-50帧

        感觉没有UI反而比没有场景提升更多。

       看来有必要对UI进行适当的分析。额,发现似乎是因为一开始字体的初始化贴图,这个看来暂时没有更好的办法,而卡顿部分则是特效引起的。我们的特效虽然不华丽,但性能确实堪忧。这种事情真的有点无奈,没有给力美术,非常郁闷啊。。。

     


2014-08-29 17:34:23 qq_19929447 阅读数 11045

    

在贴图的批处理上,NGUI的做法比较死板,依然是根据让多个图片打成一个图集,然后通过不同的UV坐标来进行绘制图集上的精灵。因此,NGUI在极限情况下,能够做到整个UI只消耗一个DC。但同时这也带来了一个弊端,就是在UI动画的效率上,会很低。当界面有动画时,UIPanel的CPU占用率会急剧上升,并出现跳帧情况,让总体的帧率方差变大。而新UI系统则用了另外一种做法,去除图集的概念,并对相同图片进行合并,在极限情况下,画10个不同的图片,最少需要消耗10个DC。当两个相同的图片的深度之间,需要绘画其他UI并与这两个图片的任意一个有像素交叉时,这两个图片不进行合并,因此,对于动画的效率,要比NGUI高,跳帧情况少,帧率较为稳定。

   另个较大的变化是,因为去除了图集,所以新UI就解决了NGUI中,图集出现大量黑色空白区域的问题,总体减少了内存占用。

   资源打包上,因为新UI的图片资源全都是零散的单个图片,因此很难做到动态载入一个UI预设,因为需要关联的图片太多,步骤比较复杂。可能需要考虑所有UI资源常驻。经过计算测试,对于一般的手游来说,基本可以应付。若要进行较好的优化,则需要进行动态加载,需要把每一张图打成一个包,最后根据情况,动态加载图片。


最终结论是,若游戏中,静态UI偏多(即没有多少UI动画)则用NGUI效率较高,若动态UI偏多(UI动画多且频繁),则UGUI效率要高出很多


2019-01-22 10:32:20 jiaoqiao123 阅读数 591

有时希望录一小段unity某个摄像机的画面作为演示demo,虽然OpenCV是图像处理库,但是录一小段视频还是可以实现的,具体过程如下,只需给摄像机贴上一个脚本。

大概有几个需要注意的地方:

1、Texture2D的创建是宽*高,但Mat是高*宽

2、Texture2D是RGB色彩,而需要被VedioWriter使用的是BGR的Mat对象,需要用  Imgproc.cvtColor这个方法转换

3、使用OnPostRender()进行每帧的采集,这个函数是在每帧渲染完成后调用的

4、VedioWriter最好创为fourcc('M', 'J', 'P', 'G'),并且保存为avi格式

5、录制完后一定要release掉VedioWriter,否则视频可能打不开

6、下面给出代码需要自己添加按钮并绑定其中的OnClick()方法

using UnityEngine;
using OpenCVForUnity;
using UnityEngine.UI;
public class lushipin : MonoBehaviour
{
    const int maxframecount = 1000;    //最大录制帧数,按实际情况修改
    
    int framecount;                    //当前帧 

    Texture2D ScreenTexture;           //截图的texture2D
    
    Mat FrameRgbMat;                   //截图的Mat
    
    VideoWriter Writer;                //OpenCV的VedioWriter

    bool IsRecording;                  //是否在录制的flag

    void Start()
    {
        Writer = new VideoWriter(@"D:\opencvimage\2.avi", VideoWriter.fourcc('M', 'J', 'P', 'G'), 30, new OpenCVForUnity.Size(Screen.width, Screen.height));
        if (!Writer.isOpened())
        {
            Debug.LogError("writer.isOpened() false");
            Writer.release();
            return;
        }
        FrameRgbMat = new Mat(Screen.height, Screen.width, CvType.CV_8UC3);
        ScreenTexture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
        framecount = 0;
        IsRecording = false;
    }
    public void OnClick()           //注意public 与按钮绑定的方法,用于开始或停止录制
    {
        if (IsRecording == false)
        {
            IsRecording = true;
            Debug.Log("开始录制");
        }
        else
        {
            IsRecording = false;
            Debug.Log("录制结束");
            if (Writer != null)
                Writer.release();
        }
    }
    void OnPostRender()              //每渲染完一帧后
    {
        if (IsRecording)
        {
            if (framecount >= maxframecount ||FrameRgbMat.width() != Screen.width || FrameRgbMat.height() != Screen.height)     //达到最大帧数
            {
                IsRecording = false;
                Debug.Log("录制结束");
                if(Writer!=null)
                Writer.release();
                return;
            }
            framecount++;
            ScreenTexture.ReadPixels(new UnityEngine.Rect(0, 0, Screen.width, Screen.height), 0, 0);
            ScreenTexture.Apply();
            Utils.texture2DToMat(ScreenTexture, FrameRgbMat);
            Imgproc.cvtColor(FrameRgbMat, FrameRgbMat, Imgproc.COLOR_RGB2BGR);
            Writer.write(FrameRgbMat);
            Debug.Log("已录制:" + framecount.ToString()+"帧");
        }
    }
    void OnApplicationQuit()
    {
        Debug.Log("退出");
    }
}

附:绑定按钮触发方法

没有更多推荐了,返回首页