为什么我辐射4核子世界挥40多fps

为什么打核子危机这张图fps会狂掉?_csgo吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:884,868贴子:
为什么打核子危机这张图fps会狂掉?
同画质,打dust2能跑80fps,打核子危机只有50,为什么啊
地图模型复杂
因为链式反应计算量大 ?﹏﹏ 第一淡对
使用耀眼的挽尊卡挽回他的尊严!效果:csgo吧经验+7
同狂掉,就平时三分之二
80fps能玩?
nuke地图外的河一直在流动着的,不知道这有啥必要
新nuke就是一张失败的图,图外背景狂吃fps,地图颜色太彩,我d2 200左右,nuke外厂就只能在80到100,鼠标都拉不稳
新nuke明显和别的地图画风不一样……各种高清材质……
地图有瑕疵
颜色太干扰视线了,完全瞎眼睛
材质包太高分辨率
80能玩??我感觉低于100都打不到人呢
nuke让无数人换电脑了
锁60帧的路过
35左右的还有救吗
玩玩其他新图更卡,我基本在40左右
我这台破电脑 其他能玩 就nuke那张图 一进直接掉 有毒
没办法就是这样的,外场狂掉80帧
这个高低是看图像复杂程度嘛 不同很正常啊 nuke和dust 复杂程度 色彩上都不一样啊
a点掉帧最多
官方更新说明里有写,这次大行动的地图都用了新的光照算法,所以掉帧很正常
贴图吃显卡?
有效解決FPS過高的問題
本子炼狱100左右,核子直接掉,家里台式炼狱280,核子经常100多……
贴吧热议榜
使用签名档&&
保存至快速回贴补丁搜索:
辐射4 核子世界DLC偷跑版[适用英文版](感谢游侠会员thegfw原创制作)
==&&ed2k链接下载辐射4 核子世界DLC偷跑版[适用英文版](感谢游侠会员thegfw原创制作) eD2k下载地址1000 MB1000 MB357.53 MB1000 MB全选下载选中文件复制选中链接*需使用迅雷、QQ旋风或电驴下载==&&由800vod提供==&&由51mag提供==&&由99DDD提供
玩家还下载了这些补丁
游戏运行必备补丁
最新更新TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
年度最热门TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
本周关注TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
最新更新TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
年度最热门TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&&
本周关注TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
最新更新TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
年度最热门TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
本周关注TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
最新更新TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
年度最热门TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
本周关注TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
最新更新TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
年度最热门TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
本周关注TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
最新更新TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
年度最热门TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
本周关注TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
最新更新TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
年度最热门TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
本周关注TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
最新更新TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
年度最热门TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
本周关注TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
最新更新TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
年度最热门TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
本周关注TOP10
1&&2&&3&&4&&5&&6&&7&&8&&9&&10&
热门攻略专辑
热门补丁推荐
周人气排行榜
精品手机游戏
精彩高清图推荐
| 增值电信业务经营许可证 浙B2- |
浙网文[1 | CopyRight (C)
ALi213.Net All Right Reserved 游侠网 版权所有努力加载中,稍等...
暂无新消息
努力加载中,稍等...
已无更多消息...
这些人最近关注了你
努力加载中,稍等...
已无更多消息
努力加载中,稍等...
已无更多消息
& Unity3D:FPS——用于测试性能
Frames Per Second Measuring Performance
征集热心朋友翻译文章,奖励规则:每100汉字奖励10QB,30天内互动奖励0 - 50QB.
翻译请求:专家推荐
该文章来自用户转载
Use physics to create an ever-growing atomic nucleus.Use the profiler to investigate performance.Measure and display the frame rate.Prevent the creation of temporary strings.Stabilize the frame rate by averaging multiple frames.Colorize the frame rate display.In this tutorial we'll create a simple test scene and then measure its performance. We'll first examine the profiler, then we'll create our own frame rate counter.This tutorial requires a basic understanding of scripting in Unity. It has been made for Unity 5.0.1 and up. If you're new, have a look at&&first.Smash together spheres until your frame rate tanks.Building an Atomic NucleusWe need a test scene. One that ideally covers both high and low performance situations. I suggest we create an atomic nucleus by fusing more and more nucleons together. As the nucleus gets bigger, performance will worsen.The nucleons will be simple spheres that will be attracted to the center of the scene, where they will bunch up and form a ball. This is of course not a correct representation of an atom, but that's not the point.We can model a nucleon with a default sphere and a custom&Nucleon&component. This component makes sure that a rigidbody is attached to its object and then simply pulls it towards the origin. The strength of the pull is determined by a configurable attraction force and the distance from the center.1234567891011121314151617using UnityE&[RequireComponent(typeof(Rigidbody))]public class Nucleon : MonoBehaviour {&&&&&public float attractionF&&&&&R&&&&&void Awake () {&&&&&&&&body = GetComponent&rigidbody&();&&&&}&&&&&&&&&void FixedUpdate () {&&&&&&&&body.AddForce(transform.localPosition * -attractionForce);&&&&}}&/rigidbody&Some access modifiers are missing?Create two nucleon prefabs, one for protons and another for neutrons. Give each a different material so they look different. We could suffice with only one nucleon type, but that's boring to look at.&Nucleon prefabs.To spawn these nucleons we need to create another component,&NucleonSpawner. It needs to know the time interval between spawns, how far away from the center to spawn, and what to spawn.12345678910using UnityE&public class NucleonSpawner : MonoBehaviour {&&&&&public float timeBetweenS&&&&&public float spawnD&&&&&public Nucleon[] nucleonP}Create an empty game object, attach a&NucleonSpawner&component, and configure it as you like.Nucleon spawner.To spawn at regular intervals, we need to keep track of the time since the last spawn. We can do this with a simple&&method.123456789float timeSinceLastS&void FixedUpdate () {&&&&timeSinceLastSpawn += Time.deltaT&&&&if (timeSinceLastSpawn &= timeBetweenSpawns) {&&&&&&&&timeSinceLastSpawn -= timeBetweenS&&&&&&&&SpawnNucleon();&&&&}}Why use FixedUpdate and not Update?The actual spawning consists of three steps. Pick a random prefab, instantiate it, and give it a random position at the desired distance.12345void SpawnNucleon () {&&&&Nucleon prefab = nucleonPrefabs[Random.Range(0, nucleonPrefabs.Length)];&&&&Nucleon spawn = Instantiate&nucleon&(prefab);&&&&spawn.transform.localPosition = Random.onUnitSphere * spawnD}&/nucleon&Building a nucleus through bombardment.Playing this scene should result in spheres shooting towards the center. They will overshoot for a while, until they collide with each other so much that a ball is formed. This ball will keep growing, physics computations will become more complex, and at some point you will notice a drop in frame rate.If it takes too long for you to see performance worsen, you can increase the spawn rate. Speeding up time by increasing the time scale works as well. You can find it via&Edit / Project Settings / Time. You can also decrease the&Fixed Timestep, which will result in more physics calculations per second.Unity time settings.Why is motion not fluid for low time scales?Using the ProfilerNow that we have a scene that will eventually bring down the frame rate of any machine, it is time to measure the actual performance. The quickest thing you can do is enable the statistics overlay of the game view.Game view statistics overlay.However, the frame rate shown there isn't accurate at all, it's more like a rough guess. We can do better by opening Unity's profiler, via&Window / Profiler. The profiler gives us a lot of useful information, especially the CPU usage and memory data.The profiler, showing lots of vsync time.If vsync is enabled, it will likely dominate the CPU graph at the start. To get a better idea of how much CPU resources our scene needs, turn vsync off. You can do this via&Edit / Project Settings / Quality. It is found at the bottom, under the&Other&heading.No more vsync.I am getting very high frame rates now!Now you can get a better look at the CPU usage. In my case physics requires most time, followed by rendering, and then my scripts. This remains true for a long time, even though everything will slow down as the sphere count goes up.Profiler without vsync.There are also two unexpected observations that we can make. First, there are occasional spikes of CPU usage. Second, the memory graph shows frequent GC allocation spikes, which indicates that there is memory being allocated and subsequently freed. As we're only creating new objects and never throw anything away, this is odd.Both phenomena are caused by the Unity editor. The CPU spikes happen whenever you select something in the editor. The memory allocations are caused by a call to&GameView.GetMainGameViewRenderRect, which is invoked by the editor. There is additional overhead as well, especially if you have both the game and scene view visible at the same time. In short, the editor itself interferes with our measurements.You can still get plenty of useful information from in-editor profiling, but if you want to eliminate the editor itself from your measurements, you have to make a standalone build. You can still use the profiler if you make a development build and even automatically connect to it when running your app. You can configure this via&File / Build Settings...The profiler attached to a standalone app.When profiling a standalone build, the data looks quite different. Memory allocations are now only caused by nucleons being spawned, and no more garbage collection occurs. In my case rendering takes more time, because I'm running the app full-screen instead of in a small game view. Also, the scripts are so insignificant that they're not even visible in the graph.Measuring Frames Per SecondThe profiles gives us useful information, but it still doesn't gives us a good measurement of the frame rate. The FPS numbers shows are just 1 divided by the CPU time, which is not the actual frame rate that we're getting. So let's measure it ourselves.We need a simple component that tells us the current frames per second that our app is running at. A single public property suffices. We make it an integer because we don't really need fractional precision.123456using UnityE&public class FPSCounter : MonoBehaviour {&&&&&public int FPS { get; private set; }}How does that property work?We measure the frames per second each update by dividing 1 by the time delta of the current frame. We cast the result to an integer, effectively rounding down.123void Update () {&&&&FPS = (int)(1f / Time.deltaTime);}However, there is a problem with this approach. The time delta is not the actual time it took to process the last frame, it is influence by the current time scale. This means that our FPS will be wrong unless the time scale is set to 1. Fortunately, we can also ask Unity for the unscaled time delta.123void Update () {&&&&FPS = (int)(1f / Time.unscaledDeltaTime);}Some kind of UI is needed to show the FPS. Let's use Unity's UI for that. Create a canvas with a panel inside it that in turn contains a text object. These can be added via the&GameObject / UI&submenu. When adding a canvas you'll also get an&EventSystem&object to handle user input, but we don't need that, so you can remove it.UI object hierarchy.I used the default canvas settings, except that I made it pixel-perfect.A pixel-perfect canvas.The panel is used to create a semitransparent black background for the FPS label. That way it will always be readable. I put it at the top-left corner of the window. Set its anchor to top-left so it remains in place regardless of the window's size. Set its pivot to (0,1) for easy placement.Position the label inside the panel in a similar way. Make it white bold text, centered both horizontally and vertically. Design the whole thing so it snugly fits two digits.&&Building the UI.Now we need to bind the FPS value to the label. Let's create a component for this purpose. It needs an&FPSCounter&component to retrieve the value from, and a reference to a&&label from the&UnityEngine.UI&namespace to assign the value to.12345678using UnityEusing UnityEngine.UI;&[RequireComponent(typeof(FPSCounter))]public class FPSDisplay : MonoBehaviour {&&&&&public Text fpsL}Add this component to our panel and hook it up. We attach it to the panel because that's our whole FPS display, not to the label. We'll include more labels later.Setting up the display.The display component simply has to update the label's text each frame. Let's cache the reference to the counter so we don't need to invoke&&every time.123456789FPSCounter fpsC&void Awake () {&&&&fpsCounter = GetComponent&fpscounter&();}&void Update () {&&&&fpsLabel.text = fpsCounter.FPS.ToString();}&/fpscounter&The FPS label is now updating! But as we designed it for two digits, it will show useless values whenever our frame rate exceeds 99 per second. So let's clamp displayed value. Anything above 99 performs good enough anyway.123void Update () {&&&&fpsLabel.text = Mathf.Clamp(fpsCounter.FPS, 0, 99).ToString();}Now we can see the frame rate.Everything appears to work fine now, but there is a subtle problem. We are now creating a new string object each update, which is discarded the next update. This pollutes the managed memory, which will trigger the garbage collector. While this isn't a big deal for desktop apps, it is more troublesome for devices with little memory to spare. It also pollutes our profiler data, which is annoying when you're hunting for allocations.Temporary string objects are created each update.Can we get rid of these temporary strings? The value that we are displaying can be any integer between 0 and 99. That's 100 different strings. Why not create all these strings once and reuse them, instead of recreating the same content all the time?12345678910111213141516static string[] stringsFrom00To99 = {&&&&"00", "01", "02", "03", "04", "05", "06", "07", "08", "09",&&&&"10", "11", "12", "13", "14", "15", "16", "17", "18", "19",&&&&"20", "21", "22", "23", "24", "25", "26", "27", "28", "29",&&&&"30", "31", "32", "33", "34", "35", "36", "37", "38", "39",&&&&"40", "41", "42", "43", "44", "45", "46", "47", "48", "49",&&&&"50", "51", "52", "53", "54", "55", "56", "57", "58", "59",&&&&"60", "61", "62", "63", "64", "65", "66", "67", "68", "69",&&&&"70", "71", "72", "73", "74", "75", "76", "77", "78", "79",&&&&"80", "81", "82", "83", "84", "85", "86", "87", "88", "89",&&&&"90", "91", "92", "93", "94", "95", "96", "97", "98", "99"};&void Update () {&&&&fpsLabel.text = stringsFrom00To99[Mathf.Clamp(fpsCounter.FPS, 0, 99)];}By using a fixed array of string representations of every number that we might need, we have eliminated all temporary string allocations!Averaging Frames Per SecondUpdating the FPS value each frame has an unfortunate side effect. The label will fluctuate constantly when the frame rate isn't stable, making it hard to get a useful reading. We could update the label only once in a while, but then we would no longer get a good impression of how the frame rate is behaving.A possible solution is to average the frame rate, smoothing the impact of sudden changes, producing a less jittery value. Let's adjust&FPSCounter&so it does this over a configurable range of frames. Setting this value to 1 would be the same as not averaging at all, so it is effectively optional.1public int frameRange = 60;Configurable frame range.Let's change the property name from&FPS&to&AverageFPS, as that is a better description of the value it now represents. Either use your IDE to refactor the name, or manually update the display component to use the new name.1public int AverageFPS { get; private set; }Now we need a buffer to store the FPS values of multiple frames, plus an index so we know where to put the data of the next frame.12int[] fpsBint fpsBufferIWhen initializing this buffer, make sure that&frameRange&is at least 1, and set the index to 0.1234567void InitializeBuffer () {&&&&if (frameRange &= 0) {&&&&&&&&frameRange = 1;&&&&}&&&&fpsBuffer = new int[frameRange];&&&&fpsBufferIndex = 0;}The&&method becomes a little more complicated. It begins by initializing the buffer if this is needed, either because we just started or because&frameRange&has changed. Then the buffer has to be updated, after which the average FPS can be calculated.1234567void Update () {&&&&if (fpsBuffer == null || fpsBuffer.Length != frameRange) {&&&&&&&&InitializeBuffer();&&&&}&&&&UpdateBuffer();&&&&CalculateFPS();}Updating the buffer is done by storing the current FPS at the current index, which is then incremented.123void UpdateBuffer () {&&&&fpsBuffer[fpsBufferIndex++] = (int)(1f / Time.unscaledDeltaTime);}But we'll quickly fill our entire buffer, and then what? We'll have to discard the oldest value before adding the new one. We could shift all values one position, but the average doesn't care about the order that the values are in. So we can just wrap the index back to the start of the array. That way we always override the oldest value with the newest, once the buffer has been filled.123456void UpdateBuffer () {&&&&fpsBuffer[fpsBufferIndex++] = (int)(1f / Time.unscaledDeltaTime);&&&&if (fpsBufferIndex &= frameRange) {&&&&&&&&fpsBufferIndex = 0;&&&&}}Calculating the average is a simple matter of summing all values in the buffer and dividing by the amount of values.1234567void CalculateFPS () {&&&&int sum = 0;&&&&for (int i = 0; i & frameR i++) {&&&&&&&&sum += fpsBuffer[i];&&&&}&&&&AverageFPS = sum / frameR}Our average frame rate now works, and with a reasonable frame range it is a lot easier to get a good reading. But we can do even better. As we now have data from multiple frames, we can also expose the highest and lowest FPS in this range too. This gives us a lot more information than just an average.12public int HighestFPS { get; private set; }public int LowestFPS { get; private set; }We can find these values at the same time that we are calculating the sum.123456789101112131415161718void CalculateFPS () {&&&&int sum = 0;&&&&int highest = 0;&&&&int lowest = int.MaxV&&&&for (int i = 0; i & frameR i++) {&&&&&&&&int fps = fpsBuffer[i];&&&&&&&&sum +=&&&&&&&&if (fps & highest) {&&&&&&&&&&&&highest =&&&&&&&&}&&&&&&&&if (fps & lowest) {&&&&&&&&&&&&lowest =&&&&&&&&}&&&&}&&&&AverageFPS = sum / frameR&&&&HighestFPS =&&&&LowestFPS =}Our&FPSDisplay&components can now bind two additional labels.12345678910public Text highestFPSLabel, averageFPSLabel, lowestFPSL&void Update () {&&&&highestFPSLabel.text =&&&&&&&&stringsFrom00To99[Mathf.Clamp(fpsCounter.HighestFPS, 0, 99)];&&&&averageFPSLabel.text =&&&&&&&&stringsFrom00To99[Mathf.Clamp(fpsCounter.AverageFPS, 0, 99)];&&&&lowestFPSLabel.text =&&&&&&&&stringsFrom00To99[Mathf.Clamp(fpsCounter.LowestFPS, 0, 99)];}Add two more labels to the UI and hook them all up. I put the highest FPS at the top and the lowest FPS at the bottom, with the average FPS in the middle.&&More information, less jitter.Coloring the LabelsAs a final touch to the FPS labels, we can colorize them. This can be done by associating colors with FPS values. Such an association can be represented with a custom struct.12345[System.Serializable]private struct FPSColor {&&&&public C&&&&public int minimumFPS;}As&FPSDisplay&is the only thing that will use this structure, we put the struct definition directly inside that class and make it private so that it won't show up in the global namespace. Make it serializable so that it can be exposed by the Unity editor.Now add an array of these struct so we can configure the coloring of the FPS labels. We'd typically add a public field for that, but we can't do that because the struct itself is private. So make the array private as well and give it the&&attribute so Unity exposes it in the editor and saves it.12[SerializeField]private FPSColor[]Go ahead and add some colors! Make sure that there is at least one entry, order them from highest to lowest FPS, with the last entry for 0 FPS.Coloring.Before applying the colors to the labels, restructure the&&method by introducing a separate&Display&method that takes care of adjusting a single label.123456789void Update () {&&&&Display(highestFPSLabel, fpsCounter.HighestFPS);&&&&Display(averageFPSLabel, fpsCounter.AverageFPS);&&&&Display(lowestFPSLabel, fpsCounter.LowestFPS);}&void Display (Text label, int fps) {&&&&label.text = stringsFrom00To99[Mathf.Clamp(fps, 0, 99)];}The correct color can be found by looping through the array until the minimum FPS for a color is met. Then set the color and break out of the loop.123456789void Display (Text label, int fps) {&&&&label.text = stringsFrom00To99[Mathf.Clamp(fps, 0, 99)];&&&&for (int i = 0; i & coloring.L i++) {&&&&&&&&if (fps &= coloring[i].minimumFPS) {&&&&&&&&&&&&label.color = coloring[i].&&&&&&&&&&&&break;&&&&&&&&}&&&&}}Why did my labels disappear?Colored fps labels.Done! Enjoy watching your FPS tank, in color!
Unity3D:FPS——用于测试性能
版权所有,禁止匿名转载;禁止商业使用;禁止个人使用。
译者: 张乾光(星际迷航)
审校:崔国军(飞扬971)使用物理学来创建一个不断增长的原子核。使用分析器来研究性能。测量和显示帧速率。阻止创建临时字符串。通过对多个帧取平均值来获得稳定的帧速率。帧速率用彩色显示出来。在这篇教程中,我们将创建一个简单的测试场景,然后测量其性能。我们将首先检查分析器,然后我们将创建自己的帧速率计数器。这篇教程需要你对Unity中的脚本有基本的了解。它可以在Unity 5.0.1及以上的版本上运行。如果你是Unity方面的新手,请先看下《分形的构造-通过递归提供足够的细节》这篇文章。 碎片一起组成一个球,直到你的帧速率掉下来为止。构建一个原子核我们需要一个测试场景。 这是一个理想地可以涵盖高性能和低性能情况的场景。我建议我们通过融合越来越多的核子来创建一个原子核。随着核越来越大,性能将逐步恶化。核子将是简单的球体,它们将被吸引到场景的中心,在那里他们将组成一个球。这当然不是一个原子的正确表示,但这不是重点。我们可以使用默认球体和自定义的Nucleon组件来对核子进行建模。这个组件确保刚体连接到其对象,然后简单地将其拉向原点。拉力的强度由可配置的吸引力和离中心的距离来确定。using UnityE[(typeof())]public class Nucleon :
public float attractionF
body= &&();
body.AddForce(transform.localPosition* -attractionForce);
}} 缺少某些访问修饰符?创建两个核子预制件,一个用于质子,另一个用于中子。给这两个核子预制件不同的材质,使它们看起来不同。如果只有只有一个核子类型的话,也可以满足我们的需求,但这样的话,会看起来比较无聊: 核子的预制件。为了产生这些核子,我们需要创建另一个组件,NucleonSpawner。它需要知道核子产生之间的时间间隔,以及在出生的时候核子离球的中心有多远,以及要产生哪个核子。using UnityEpublic class NucleonSpawner :
public float timeBetweenS
public float spawnD
public Nucleon[] nucleonP}创建一个空的游戏对象,附加一个NucleonSpawner组件,并根据需要对它进行配置。核子的生成器。为了定期产出核子,我们需要跟踪自上次产出核子后的时间 我们可以使用一个简单的FixedUpdate方法
float timeSinceLastS
timeSinceLastSpawn+= .deltaT
if (timeSinceLastSpawn &=timeBetweenSpawns) {
timeSinceLastSpawn-= timeBetweenS
SpawnNucleon();
} 为什么使用FixedUpdate函数而不是Update 函数?实际产出核子包括三个步骤。 选择一个随机预制件,实例化这个预制件,给这个预制件的实例一个随机位置并能满足所需的距离。
void SpawnNucleon () {
Nucleon prefab = nucleonPrefabs[.Range(<span style="color:#, nucleonPrefabs.Length)];
Nucleon spawn = &Nucleon&(prefab);
spawn.transform.localPosition= .onUnitSphere* spawnD
}建立核子的中心。播放这个场景应该会导致所有的球体向中心聚集。它们将越过中心一段时间,直到它们彼此碰撞来形成一个球体。这个新形成的球体将继续增长,物理计算将变得更加复杂,在某些时候你会注意到帧速率的下降。如果需要太长时间才能看到性能恶化的话,可以提高粒子的生成率。通过增加时间长度来对时间加速的话,效果也很好。你可以通过编辑/项目设置/时间找到对时间的设置。你还可以减少固定时间步长,这将导致每秒更多的物理计算。Unity的时间部分的设置。为什么运动在低时间步长上不流畅?使用分析器现在我们有一个场景,这个场景最终会降低任何机器的帧速率,现在是衡量实际性能的时候了。你现在可以选择的最快的事情是启用游戏视图里面的统计信息叠加。游戏视图里面的统计信息叠加。然而,这里显示的帧率根本不准确,它更像是一个粗略的猜测。我们可以通过打开Unity的分析器做得更好,打开Unity的分析器可以通过Window / Profiler做到。分析器为我们提供了很多有用的信息,特别是CPU使用率和内存数据。分析器,显示了大量了垂直同步的时间。如果启用了垂直同步,它可能在开始的时候占据了CPU的图形。要更好地了解我们的场景需要多少的CPU资源,请关闭垂直同步。你可以通过编辑/项目设置/质量来执行这个操作。这个设置在底部,在其他标题的下面。没有垂直同步以后的效果。我现在得到了非常高的帧速率!现在,你可以更好地了解CPU的使用情况。在我的这个情况下,物理部分占据了大多数的时间,然后是渲染,再然后是我的脚本部分。这在很长一段时间里都会如此,即使一切都会减慢,变慢是因为球体数量的增加。没有垂直同步以后的分析器结果。这里面还有两个意想不到的地方。 首先,有偶尔的CPU使用峰值。 第二,内存图显示频繁的垃圾回收分配尖峰,这表示存在被分配并随后被释放的内存。 因为我们只是创造新的对象,从不释放任何东西,出现这种情况是很奇怪的。这两种现象都是由Unity编辑器引起的。每当你在编辑器中选择某个内容时,CPU的峰值都会出现。 内存分配是是由调用GameView.GetMainGameViewRenderRect引起的,它由编辑器调用。特别是如果你的游戏和场景视图同时可见的话,还有额外的开销。简而言之,编辑器本身干扰了我们的测量。你仍然可以从编辑器内部的分析中获得大量有用的信息,但是如果要从测量中消除编辑器本身的影响,则必须进行独立构建。如果您要进行开发构建,甚至在运行应用程序时自动连接,你仍然可以使用分析器。你可以通过文件/构建设置来调整这个配置。。。分析器附加到一个单独的应用程序上。当对独立构建进行性能分析的时候,数据看起来完全不同。内存分配现在只是由产生的核子引起的,并且不再发生垃圾收集的情况。在我的例子之中,渲染需要更多的时间,因为我全屏运行应用程序,而不是在一个小游戏视图运行应用程序。此外,脚本的影响是如此微不足道,它们甚至在整个图形中不可见。测量每秒的帧速率这些配置信息为我们提供了有用的信息,但是它仍然不能很好地测量帧速率。 FPS数字显示的只是1除以CPU的处理时间得到的结果,这不是我们的实际帧速率。所以,让我们自己测量实际帧速率。我们需要一个简单的组件,告诉我们应用程序运行在每秒的当前帧速率。单个公共属性就足够了。我们把这个公共属性设置程一个整数,因为我们不需要分数这么高的精度。using UnityEpublic class FPSCounter :
public int FPS { get; private set; }} 这个属性如何工作?我们通过将1除以当前帧的时间增量来测量每秒更新的帧数。我们将结果转换为整数,执行的是向下取整。
FPS= (int)(<span style="color:#f / .deltaTime);
}然而,这种方法有一个问题。时间增量不是处理最后一帧所需的实际时间,它会受到当前时间尺度的影响。这意味着我们的帧率将是错误的,除非时间尺度设置为1。幸运的是,我们也可以访问Unity未缩放的时间增量。
FPS= (int)(<span style="color:#f / .unscaledDeltaTime);
}需要一些UI来显示我们的帧率。让我们使用Unity的UI。创建一个在其中包含了一个面板的画布,这个面板又包含一个文本对象。这些可以通过GameObject / UI子菜单进行添加。当添加一个画布的时候,你还会得到一个EventSystem对象来处理用户输入,但我们不需要这个对象,所以你可以删除它。UI物体的层次结构。我使用默认的画布设置,除了我选择了“像素完美展现”。一个“像素完美展现”的画布。这个面板用于为帧率标签创建半透明的黑色背景。这样的话,它总是可读的。 我把它放在窗口的左上角。将它的锚点设置为左上角,以便它保持在原位,而与窗口的大小无关。将其枢轴设置为(0,1),以方便放置。以类似的方式将标签放置在面板内。将其设置为白色粗体文本,水平和垂直居中。需要对整个东西进行设计,以使其贴合两位数的展现。
构建UI。现在我们需要将帧率值绑定到标签。让我们为此创建一个组件。 它需要一个FPSCounter组件来从中检索值,以及需要一个对来自UnityEngine.UI命名空间的Text标签的引用,以便将值分配给它。using UnityEusing UnityEngine.UI;[(typeof(FPSCounter))]public class FPSDisplay :
fpsL}将这个组件添加到我们的面板中并进行挂接。我们将它附加到面板之上,因为这是我们的整个的帧率显示,而不是标签。稍后我们会添加更多的标签。设置显示的相关信息。显示组件仅需要在每帧更新标签的文本。让我们缓存对计数器的引用,所以我们不需要每次都调用GetComponent。
FPSCounter fpsC
fpsCounter= &FPSCounter&();
fpsLabel.text= fpsCounter.FPS.ToString();
}帧率标签现在可以更新了! 但是,因为我们是为两位数的展示设计的标签,每当我们的帧速率超过99每秒的时候,它将显示无效的值。所以让我们钳制显示的数值。 大于99的任何东西都表明现在帧率不错。
fpsLabel.text= .Clamp(fpsCounter.FPS, <span style="color:#, <span style="color:#).ToString();
} 现在我们可以看到帧速率了。现在一切似乎工作正常,但是这里面有一个微妙的问题。我们现在正在为每个更新创建一个新的字符串对象,这将在下一次更新的时候丢弃。这会污染受管控内存,并将触发垃圾回收器。虽然这对于桌面应用程序来说不是大问题,但对于内存很少的设备来说会非常的麻烦。它也会污染我们的分析器数据,当你在寻找分配内存的地方的时候,这是非常烦人的。每次更新都会创建临时字符串对象。我们可以摆脱这些临时字符串吗? 我们显示的值可以是0到99之间的任何整数。这是100个不同的字符串。为什么不一次创建所有这些字符串并重用它们呢,而不是一直重新创建相同的内容?
static string[] stringsFrom00To99 = {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99"
fpsLabel.text= stringsFrom00To99[.Clamp(fpsCounter.FPS, <span style="color:#, <span style="color:#)];
}通过使用一个固定数组,里面包含我们可能需要的每个数字的字符串表示的,我们已经消除了所有临时的字符串分配!下载地址:对每秒帧数取平均更新每帧的帧率值有不良的副作用。当帧速率不稳定的时候,标签的值就会不断波动,这使得很难获得有用的读数。我们可以在一段时间内只更新标签的值一次,但是这样的话我们将不再能知道帧速率是如何变动的。一种可能的解决方案是对帧速率进行平均,来平滑突然变化所带来的影响,产生较小的抖动值。让我们调整FPSCounter,使其在可配置的帧范围内做这个事情。将这个值设置为1将与不进行平均得到相同的结果,因此这个事情是可选的。
public int frameRange = <span style="color:#;可配置的帧范围。让我们将属性名称从FPS更改为AverageFPS,因为这是对现在表示的值的更好的描述。 使用你的集成开发环境重构该名称,或者手动更新显示组件以使用新名称。
public int AverageFPS { get; private set; }现在我们需要一个缓冲区来存储多个帧的帧率值,加上一个索引,以便我们知道将下一帧的数据放在哪里。
int fpsBufferI初始化这个缓冲区的时候,请确保frameRange至少为1,并将索引设置为0。
void InitializeBuffer () {
if (frameRange &= <span style="color:#){
frameRange= <span style="color:#;
fpsBuffer= new int[frameRange];
fpsBufferIndex= <span style="color:#;
}Update方法变得有点复杂。它在开始的时候会初始化缓冲区,如果我们刚刚开始,或者因为frameRange已经改变的话,这种初始化缓冲区是必需的。 然后缓冲器必须更新,之后可以计算平均帧速率。
if (fpsBuffer == null || fpsBuffer.Length != frameRange) {
InitializeBuffer();
UpdateBuffer();
CalculateFPS();
}通过将当前帧速率存储在当前索引处来更新缓冲器,然后递增当前索引。
void UpdateBuffer () {
fpsBuffer[fpsBufferIndex++]= (int)(<span style="color:#f / .unscaledDeltaTime);
}但是我们会很快填充整个缓冲区,然后会做什么? 在添加新值之前,我们必须丢弃最旧的值。我们可以将所有值移位一个位置,但是平均值不关心值的顺序。因此,我们可以将索引的位置回到数组的开头。这样,一旦缓冲区被填充的话,我们总是用最新的值覆盖最旧的值。
void UpdateBuffer () {
fpsBuffer[fpsBufferIndex++]= (int)(<span style="color:#f / .unscaledDeltaTime);
if (fpsBufferIndex &= frameRange) {
fpsBufferIndex= <span style="color:#;
}计算平均值是一个简单的事情,只需要对缓冲区中的所有值求和并除以值的数量。
void CalculateFPS () {
int sum = <span style="color:#;
for (int i = <span style="color:#;i & frameR i++) {
sum+= fpsBuffer[i];
AverageFPS= sum / frameR
}我们的平均帧速率现在可以工作了,并且有一个合理的帧范围,很容易得到一个良好的阅读体验。但我们可以做得更好。由于我们现在有多个帧的数据,我们也可以暴露在这个范围内最高和最低的帧速率。这给了我们更多的信息,而不仅仅是一个平均值。
public int HighestFPS { get; private set; }
public int LowestFPS { get; private set; }我们可以在计算总和的同时找到这些值。
void CalculateFPS () {
int sum = <span style="color:#;
int highest = <span style="color:#;
int lowest = int.MaxV
for (int i = <span style="color:#;i & frameR i++) {
int fps = fpsBuffer[i];
if (fps & highest) {
if (fps & lowest) {
AverageFPS= sum / frameR
HighestFPS=
LowestFPS=
}我们的FPSDisplay组件现在可以绑定另外两个标签。
highestFPSLabel, averageFPSLabel, lowestFPSL
highestFPSLabel.text=
stringsFrom00To99[.Clamp(fpsCounter.HighestFPS, <span style="color:#, <span style="color:#)];
averageFPSLabel.text=
stringsFrom00To99[.Clamp(fpsCounter.AverageFPS, <span style="color:#, <span style="color:#)];
lowestFPSLabel.text=
stringsFrom00To99[.Clamp(fpsCounter.LowestFPS, <span style="color:#, <span style="color:#)];
}向UI添加两个标签,并将它们全部挂起。我把最高的帧速率放在顶部,最低的帧速率放在底部,平均帧速率放在中间。
更多的信息,更少的抖动。下载地址:给标签赋予颜色作为对帧速率标签的最后修改,我们可以对它们进行着色。这可以通过将颜色与帧速率值相关联来完成。这样的关联可以用自定义结构来表示。
private struct FPSColor {
public int minimumFPS;
}因为FPSDisplay是使用这个结构的唯一的东西,我们把结构定义直接放在那个类里面,使它成为私有的结构,所以它不会出现在全局命名空间中。并且让这个结构可以序列化,以便这个结构可以通过Unity编辑器暴露出来。现在让我们添加这些结构的数组,以便我们可以配置帧速率标签的着色。我们通常添加一个公共字段,但是我们不能这样做,因为结构本身是私有的。所以把数组也设为私有,给它SerializeField属性,以便Unity可以在编辑器中暴露它并保存它。
private FPSColor[]继续并添加一些颜色! 确保至少有一个条目,将它们从最高帧速率到最低帧速率排序,最后一个条目为0 帧速率。赋予颜色。 在将颜色应用到标签之前,通过引入一个单独的Display方法来重新组织Update方法,该方法负责调整单个标签。
Display(highestFPSLabel,fpsCounter.HighestFPS);
Display(averageFPSLabel,fpsCounter.AverageFPS);
Display(lowestFPSLabel,fpsCounter.LowestFPS);
void Display ( label, int fps) {
label.text= stringsFrom00To99[.Clamp(fps, <span style="color:#, <span style="color:#)];
}通过循环遍历数组可以找到正确的颜色,直到找到满足颜色的最小帧速率。然后设置颜色并中断循环。
void Display ( label, int fps) {
label.text= stringsFrom00To99[.Clamp(fps, <span style="color:#, <span style="color:#)];
for (int i = <span style="color:#;i & coloring.L i++) {
if (fps &= coloring[i].minimumFPS) {
label.color= coloring[i].
} 为什么我的标签会消失?默认颜色的所有四个通道都会设置为零。这包括控制透明度的Alpha通道。如果你尚未更改透明度通道,则会获得完全透明的标签。彩色的帧率标签。那我们就完成了! 现在看看你的帧速率,它们现在是彩色的了!【版权声明】原文作者未做权利声明,视为共享知识产权进入公共领域,自动获得授权。
分类:程序新手圈
请勿发表无意义的内容请勿发表重复内容请勿发表交易类内容禁止发表广告宣传贴请使用文明用语其它
淫秽色情政治倾向人身攻击抄袭剽窃广告刷屏恶意挖坟冒充他人其它
登录后参与讨论。点击}

我要回帖

更多关于 核子密度仪 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信