查看: 1328|回复: 1
打印 上一主题 下一主题

unity虚拟视觉效果创建(一)

[复制链接]

5552

主题

2

听众

8万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
11

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2012-6-11 14:56:18 |只看该作者 |倒序浏览
unity虚拟视觉效果创建
Introduction,介绍
In this tutorial we'll write some C# scripts to display increasingly complex graphs. You'll learn to

create graphs, from a single line to animated volumes;

control a particle system;

write various mathematical functions;

change behavior while in play mode;

use the Start and GetComponent methods;

write loops, both single and nested;

use arrays, enumerations, and delegates.

You're assumed to know your way around Unity's editor and know the basics of creating C# scripts. If you've completed the Clock tutorial you're good to go.
Preparations
We start by opening a new project without any packages. We'll be creating our graphs inside a unit cube, placed between (0, 0, 0) and (1, 1, 1). Let's set up the editor so we get a good view of this area. The 4 Split is a handy predefined view configuration so let's select that. It's in Window / Layout / 4 Spit or in the dropdown list at the top right of the screen. Set the view mode of all of them to Textured. Also flip the perspective view around by clicking on the box at the center of the compass.

Now create a particle system via GameObject / Create Other / Particle System and set its position to (0, 0, 0). This gives us a reference point for calibrating our views. Now zoom and pan the views so they're focused on the unit cube.

Finally, select the Main Camera and make it match the perpective view via GameObject / Align With View (we did the opposite in the Clock tutorial). If that doesn't work right, make sure the correct view is active by clicking in it and then try again.


The particle system is currently producing animated particles at random, which we don't need. Disable the Ellipsoid Particle Emitter by unchecking the Emit field. This causes the preview particles to die out. Also remove the Particle Animator component, because we don't need it. This leaves us with an inert particle system that we can use to visualize graph data.


Creating the first graph
The first graph we'll create will be a simple line graph where the value of Y depends on the value of X. We'll use the positions of the particles to visualize this.

Rename the particle system object to Graph 1, create a C# script named Grapher1 as a minimal GameObject class, and drag it to our object so it gets added as a component.

using UnityEngine;
public class Grapher1 : MonoBehaviour {

}


To get to the particles, we need access to the particle emitter component first. We could do this by adding a public ParticleEmitter variable and then dragging the component to the corresponding field, like we did in the Clock tutorial. However, there's a different way that doesn't require manual configuration.

We use the GetComponent method to retrieve our particle emitter component. We do this inside the special Start method, which is called once before updates start happening. This allows us to keep out variable private, so it doesn't show up in the inspector view.

Not EllipsoidParticleEmitter?How does GetComponent work?When is Start called exactly?

using UnityEngine;
public class Grapher1 : MonoBehaviour {

private ParticleEmitter emitter;

void Start () {

emitter = GetComponent<articleEmitter>();

}

}

Using the emitter, we can produce an array of Particle s***cts which will serve as the points of our graph. To get them, we first need to ins***ct the emitter to generate a certain number of particles, then fetch those particles and store them for later use.

How much particles should we create? The more particles, the higher the sample resolution of our graph. Let's make it customizable, with a default resolution of 10.

How do arrays work?

using UnityEngine;
public class Grapher1 : MonoBehaviour {

public int resolution = 10;

private Particle[] points;

private ParticleEmitter emitter;

void Start () {

emitter = GetComponent<articleEmitter>();

emitter.Emit(resolution);

points = emitter.particles;

}

}


Now that we have the points it's time to position them along the X axis. The first point should be placed at 0 and the last should be placed at 1. All other points should be placed in between. So the distance – or X increment – between two points is 1 / (resolution - 1).

Besides the position, we can also use color to provide the same information. We'll make the red color component of the points equals to their position along the X axis.

We'll use a for loop to iterate over all points and set both their position and color, which are s***ct values of type Vector3 and Color.

How does a for loop work?What does i++ do?What does new do?

using UnityEngine;
public class Grapher1 : MonoBehaviour {

public int resolution = 10;

private Particle[] points;

private ParticleEmitter emitter;

void Start () {

emitter = GetComponent<articleEmitter>();

emitter.Emit(resolution);

points = emitter.particles;

float increment = 1f / (resolution - 1);

for(int i = 0; i < resolution; i++){

float x = i * increment;

points.position = new Vector3(x, 0f, 0f);

points.color = new Color(x, 0f, 0f);

}

}

}

So far, it doesn't work. When playing, we now get some random white particles instead of what we want. This is because the particle array that we got out of the emitter is a copy. Changing this copy doesn't affect the particles in the particle system at all. We need to assign the particle array back to the emitter. That will copy our data back into the particle system, replacing its old particles. We will do this in the Update method.

using UnityEngine;
public class Grapher1 : MonoBehaviour {

public int resolution = 10;

private Particle[] points;

private ParticleEmitter emitter;

void Start () {

emitter = GetComponent<articleEmitter>();

emitter.Emit(resolution);

points = emitter.particles;

float increment = 1f / (resolution - 1);

for(int i = 0; i < resolution; i++){

float x = i * increment;

points.position = new Vector3(x, 0f, 0f);

points.color = new Color(x, 0f, 0f);

}

}

void Update () {

emitter.particles = points;

}

}

That's it! We now get a nice black to red line of points along the X axis. How many points are shown depends on what we put in the resolution field before entering play mode.


Right now, resolution is only taken into account when the graph is initialized. Updating its value while in play mode doesn't do anything. Let's change that.

A simple way to detect a change of resolution is by storing it twice and then constantly checking whether both values are still the same. If at some point they're different, we need to rebuild the graph. We'll create a private variable currentResolution for this purpose.

using UnityEngine;
public class Grapher1 : MonoBehaviour {

public int resolution = 10;

private int currentResolution;

private Particle[] points;

private ParticleEmitter emitter;

void Start () {

emitter = GetComponent<articleEmitter>();

currentResolution = resolution;

emitter.Emit(resolution);

points = emitter.particles;

float increment = 1f / (resolution - 1);

for(int i = 0; i < resolution; i++){

float x = i * increment;

points.position = new Vector3(x, 0f, 0f);

points.color = new Color(x, 0f, 0f);

}

}

void Update () {

if(currentResolution != resolution){

// currently do nothing

}

emitter.particles = points;

}

}

Because rebuilding is almost the same as the first initialization, let's move that code into a new private method which we name CreatePoints. That way we can reuse the code. The only thing we need to add clearing any previous particles before emitting new ones.

using UnityEngine;
public class Grapher1 : MonoBehaviour {

public int resolution = 10;

private int currentResolution;

private Particle[] points;

private ParticleEmitter emitter;

void Start () {

emitter = GetComponent<articleEmitter>();

CreatePoints();

}

private void CreatePoints () {

currentResolution = resolution;

emitter.ClearParticles();

emitter.Emit(resolution);

points = emitter.particles;

float increment = 1f / (resolution - 1);

for(int i = 0; i < resolution; i++){

float x = i * increment;

points.position = new Vector3(x, 0f, 0f);

points.color = new Color(x, 0f, 0f);

}

}

void Update () {

if(currentResolution != resolution){

CreatePoints();

}

emitter.particles = points;

}

}

Now the graph is recreated as soon as we change the value of resolution. However, you'll notice that the console will spit out errors whenever resolution is equal to 1, even while typing. This is because the caluculation of increment will result in a division by zero. One way to prevent this is to make sure that resolution is always at least 2.

using UnityEngine;
public class Grapher1 : MonoBehaviour {

public int resolution = 10;

private int currentResolution;

private Particle[] points;

private ParticleEmitter emitter;

void Start () {

emitter = GetComponent<articleEmitter>();

CreatePoints();

}

private void CreatePoints () {

if(resolution < 2){

resolution = 2;

}

currentResolution = resolution;

emitter.ClearParticles();

emitter.Emit(resolution);

points = emitter.particles;

float increment = 1f / (resolution - 1);

for(int i = 0; i < resolution; i++){

float x = i * increment;

points.position = new Vector3(x, 0f, 0f);

points.color = new Color(x, 0f, 0f);

}

}

void Update () {

if(currentResolution != resolution){

CreatePoints();

}

emitter.particles = points;

}

}

Now it's time to set the Y position of the points. Let's start simple and make Y equal to X. In other words, we're visualizing the mathematical equation y = x or the function f(x) = x. To do this, we need to loop over all points, get their position, use the X value to compute the Y value, then set their new position. Once again we use a for loop, which we'll***cute each update. (The code snippet below only contains the Update method, everything else stays the same.)Why not directly set position.y?

void Update () {

if(currentResolution != resolution){

CreatePoints();

}

for(int i = 0; i < resolution; i++){

Vector3 p = points.position;

p.y = p.x;

points.position = p;

}

emitter.particles = points;

}


The next step is to make the point's green color component the same as its Y position. As red plus green becomes yellow, this will cause the line to go from black to yellow.

void Update () {

if(currentResolution != resolution){

CreatePoints();

}

for(int i = 0; i < resolution; i++){

Vector3 p = points.position;

p.y = p.x;

points.position = p;

Color c = points.color;

c.g = p.y;

points.color = c;

}

emitter.particles = points;

}





web3D纳金网www.narkii.com/
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

0

主题

1

听众

939

积分

初级设计师

Rank: 3Rank: 3

纳金币
330
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2014-12-6 10:53:00 |只看该作者
谢谢楼主的分享                       
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2025-7-21 15:00 , Processed in 0.175217 second(s), 28 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部