• Unity3D基础知识、游戏算法一网打尽。
  • Unity3D脚本--常用代码集

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                   

    1. 访问其它物体

    1) 使用Find()和FindWithTag()命令
    Find和FindWithTag是非常耗费时间的命令,要避免在Update()中和每一帧都被调用的函数中使用。在Start()和Awake()中使用,使用公有变量把它保存下来,以供后面使用。如:
      公有变量= GameObject.Find("物体名"); 或
      公有变量= GameObject.FindWithTag("物体标签名");
    2) 把一个物体拖到公有变量上
    3) 引用脚本所在的物体的组件上的参数,如下所示:

       transform.position = Vector3(0,5,4);   renderer.material.color = Color.blue;   light.intensity = 8;

    4) SendMessge()命令:一个调用其它物体上指令(即物体上的脚本中的函数)的方法

    5) GetComponent()命令:引用一个组件

    实例代码如下所示:

    #pragma strictvar thelight:GameObject;var thetxt:GameObject;var theCube1:GameObject;function Start () { thelight = GameObject.Find("Spotlight"); thetxt = GameObject.FindWithTag("txt"); theCube1 = GameObject.Find("Cube1");}function Update () if(Input.GetKey(KeyCode.L)){  thelight.light.intensity += 0.01;  thetxt.GetComponent(GUIText).text = "当前亮度:"+thelight.light.intensity; }  if(Input.GetKey(KeyCode.K)){  thelight.light.intensity -= 0.01;  thetxt.GetComponent(GUIText).text = "当前亮度:"+thelight.light.intensity; } if(Input.GetKey(KeyCode.S)){  theCube1.SendMessage("OnMouseDown"); //调用theCube1所有脚本中的OnMouseDown函数 }}

    2. 制作第一人称控制器

        第一人称控制器脚本代码如下所示:

    #pragma strictvar speed:float=6.0;var jumpspeed:float=8.0;var gravity:float=20.0;private var movedirection:Vector3=Vector3.zero;private var grounded:boolean=false;function Start () {}function FixedUpdate () if(grounded){  movedirection=Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical"));    //Transforms direction from local space to world space.  movedirection=transform.TransformDirection(movedirection);    movedirection *= speed;    if(Input.GetButton("Jump")){   movedirection.y = jumpspeed;  } }  movedirection.y -= gravity*Time.deltaTime; //Move command  var controller:CharacterController = GetComponent(CharacterController); var flags = controller.Move(movedirection*Time.deltaTime); //CollisionFlags.CollidedBelow  底部发生了碰撞 //CollisionFlags.CollidedSides 四周发生了碰撞 //CollisionFlags.CollidedAbove 顶端发生了碰撞 grounded = (flags & CollisionFlags.CollidedBelow)!=0;}//强制Unity为本脚本所依附的物体增加角色控制器组件@script RequireComponent(CharacterController)


    3. 导入3DMax模型

        在3DMax(.fbx文件)把显示单位和系统单位设置为cm,再导入到Unity3D(单位为m)中时,则大小相同。

    4. 交互功能(自动开关门)

    4.1 ControllerColliderHit(碰撞检测)    

        玩家撞到门时,门才能开。

        其相关代码如下所示,需要对模型的动画进行分割,以下脚本绑在玩家身上:

    #pragma strictprivate var doorisopen:boolean = false;private var doortimer:float = 0.0;private var currentdoor:GameObject;var door_open_time:float = 5.0;var door_open_sound:AudioClip;var door_shut_sound:AudioClip;function Update()if(doorisopen){  doortimer += Time.deltaTime;    if(doortimer > door_open_time) {   doortimer = 0.0;   door(false,door_shut_sound,"doorshut",currentdoor);  } }}//检测玩家是否与门相撞function OnControllerColliderHit(hitt:ControllerColliderHit){ //hitt为与玩家相撞的碰撞体 print("test1"); if(hitt.gameObject.tag == "playerDoor" && doorisopen == false){  print("test2");  door(true,door_open_sound,"dooropen",hitt.gameObject);  currentdoor = hitt.gameObject; }}function door(doorcheck:boolean,a_clip:AudioClip,ani_name:String,thisdoor:GameObject){ doorisopen=doorcheck; thisdoor.audio.PlayOneShot(a_clip); //声音取消3D效果,否则无法播放 thisdoor.transform.parent.animation.Play(ani_name);}

    4.2 RaycastHit(光线投射)

          玩家必须面对门时,光线投射到门时,门才能开。

          其检测碰撞代码如下所示,以下脚本绑在玩家身上

    function Update()var hit:RaycastHit; //hit为与投射光线相遇的碰撞体 if(Physics.Raycast(transform.position,transform.forward,hit,3)){    print("collider happen" + hit.collider.gameObject.tag);  if(hit.collider.gameObject.tag == "playerDoor"){   var currentdoor:GameObject = hit.collider.gameObject;   currentdoor.SendMessage("doorcheck");   print("call doorcheck");  } }}


           门身上的脚本如下所示:

    #pragma strictprivate var doorisopen:boolean = false;private var doortimer:float = 0.0;//private var currentdoor:GameObject;var door_open_time:float = 5.0;var door_open_sound:AudioClip;var door_shut_sound:AudioClip;function Update()if(doorisopen){  doortimer += Time.deltaTime;    if(doortimer > door_open_time) {   doortimer = 0.0;   door(false,door_shut_sound,"doorshut");  } }}function doorcheck()if(!doorisopen){  door(true,door_open_sound,"dooropen"); }}function door(doorcheck:boolean,a_clip:AudioClip,ani_name:String){ doorisopen=doorcheck; audio.PlayOneShot(a_clip); //声音取消3D效果,否则无法播放 transform.parent.animation.Play(ani_name);}


    4.3 OnTriggerEnter(触发器)

          只要一进入触发区域,门就可以打开。需要特别注意调整小房子的Box Collider的大小和位置。

          以下脚本绑在门所在的小房子上:

    #pragma strictfunction OnTriggerEnter (col:Collider) { //col为闯入此区域的碰撞体 if(col.gameObject.tag == "Player"){  transform.FindChild("door").SendMessage("doorcheck"); }}


    4.4 OnCollisionEnter

                 检测两个普通碰撞体之间的碰撞,需要发力,才能发生碰撞。不能与第一人称控制器发生碰撞。


    4.5 交互总结

          1) OnControllerColliderHit

              专门提供给角色控制器使用,以供角色控制器检测与其它物体发生了碰撞。

              它与触发模式的碰撞体不能发生碰撞,而且还会穿过其物体。

               以下脚本绑定在玩家(第一人称控制器)身上。

    function OnControllerColliderHit (hit:ControllerColliderHit) if(hit.gameObject.name != "Plane") gameObject.Find("wenzi").guiText.text = hit.gameObject.name;}


          2) RaycastHit

              它不是一个事件,而是一个命令,可以需要的地方调用它来发射一条光线来进行检测。

               可以与触发模式的碰撞体发生碰撞,但也会穿过其物体。   

               以下脚本绑定在玩家(第一人称控制器)身上。            

    #pragma strictvar hit:RaycastHit;function Update () if(Physics.Raycast(transform.position,transform.forward,hit,2)){  if(hit.collider.gameObject.name != "Plane"){   gameObject.Find("wenzi").guiText.text = hit.collider.gameObject.name;  } }}

          3) OnTriggerEnter

              以下脚本绑定在与第一人称控制器相撞的物体上。

    #pragma strictfunction OnTriggerEnter (col:Collider) { gameObject.Find("wenzi").guiText.text = col.gameObject.name;}

            4) OnCollisionEnter

                 检测两个普通碰撞体之间的碰撞,需要发力,才能发生碰撞。不能与第一人称控制器发生碰撞。

    5. 播放声音

    5.1 audio.Play()

        GameObject有Audio Source组件,且在Audio Source组件中设置了Audio Clip。

         

    5.2 audio.PlayOneShot

    var door_open_sound:AudioClip; //在检测面板中设置audio clip;当然必须有Audio Source组件,但不需要设置Audio Clipfunction myAudioPlay(){ audio.PlayOneShot(door_open_sound); //声音取消3D效果,否则无法播放}


    5.3 AudioSource.PlayClipAtPoint

          此种播放方式最佳,节约资源。

    var collectSound:AudioClip; //在检测面板中设置其值function pickupCell()//临时申请一个AudioSource,播放完了即时销毁 AudioSource.PlayClipAtPoint(collectSound,transform.position);}

    6. 销毁物体

        Destroy(gameObject);  //即时销毁物体

        Destroy(gameObject,3.0); // 3秒之后销毁物体

    7. 给刚体增加速度

         方法一:

    #pragma strictvar throwsound:AudioClip;var coconut_bl:Rigidbody; //为预制物体function Update () if(Input.GetButtonDown("Fire1")){  audio.PlayOneShot(throwsound);  var newcoconut:Rigidbody = Instantiate(coconut_bl,transform.position, transform.rotation);  newcoconut.velocity=transform.forward*30.0; //设置刚体速度 }}

    8. 忽视碰撞命令

       使用这两个碰撞器碰撞时不发生效果

       Physics.IgnoreCollision(transform.root.collider,newcoconut.collider,true); 


    9. 协同程序及动画播放

        协同程序:类似子线程,在运行本代码的同时,运动脚本中的其它代码。

    #pragma strict// this script will be attached to target objectprivate var beenhit:boolean = false;private var targetroot:Animation; var hitsound:AudioClip;var resetsound:AudioClip;var resettime:float=3.0;function Start () { targetroot = transform.parent.transform.parent.animation;}function OnCollisionEnter (theobject:Collision) if(beenhit == false && theobject.gameObject.name == "coconut"){  StartCoroutine("targethit"); //协同程序:类似子线程,在运行本代码的同时,运动脚本中的其它代码 }}function targethit(){ audio.PlayOneShot(hitsound); // 播放声音 targetroot.Play("down");  // 播放动画 beenhit = true;  yield new WaitForSeconds(resettime); // wait for 3s  audio.PlayOneShot(resetsound); targetroot.Play("up"); beenhit=false;}

    10. 动态添加和删除脚本

          

    #pragma strictvar obj:GameObject;var myskin:GUISkin;function Start () {}function Update () {}function OnGUI()//GUI.skin = myskin; if(GUILayout.Button("Add_Component",GUILayout.Height(40),GUILayout.Width(110))){  obj.AddComponent("xuanzhuan"); // xuanzhuan为一个脚本xuanzhuan。js } if(GUILayout.Button("Del_Component",GUILayout.Height(40),GUILayout.Width(110))){  var script:Object = obj.GetComponent("xuanzhuan");  Destroy(script); }  }

    11. 粒子系统

          粒子系统是在三维空间中渲染出来的二维图像,主要用于表现烟、火、水滴和落叶等效果。

          粒子系统由:粒子发射器、粒子动画器和粒子渲染器组成。


    12. for循环和数组

           使用Unity3D内建数组:

    var cms:Render[];fucntion Update(){   for(var co:Render in cms){      co.material.color = Color.red;   }}

           使用Unity3D非内建数组Array:

    var wenzi_bl:GUIText;var arr = new Array(9,12,65,58);  //静态数组var barr = new Array();  //动态数组fucntion Start(){   barr.Push("push1");   barr.Push("push2");   arr.Sort();   wenzi_bl.text = arr.join(",") + " ,arr长度:" + arr.length+ " >>" + barr + " barr长度:" + barr.length;}


    13. 延时函数及载入新场景

    function OnMouseDown () { audio.PlayOneShot(beep); yield new WaitForSeconds(0.35); Application.LoadLevel(levelToload);}


    14. 创建窗口及此窗口中的内容

    static var windowSwitch:boolean = false;private var windowRect = Rect(300,280,240,200);function Update()if(Input.GetKeyDown(KeyCode.Escape)){  windowSwitch = !windowSwitch; }}function OnGUI()if(windowSwitch){  windowRect = GUI.Window(0,windowRect,WindowContain,"测试窗口"); }}// show window contentsfunction WindowContain()if(GUI.Button(Rect(70,70,100,20),"关闭音乐")){  gameObject.Find("Terrain").GetComponent(AudioSource).enabled = false; }  if(GUI.Button(Rect(70,100,100,20),"播放音乐")){  gameObject.Find("Terrain").GetComponent(AudioSource).enabled = true; }  if(GUI.Button(Rect(70,130,100,20),"关闭窗口")){  windowSwitch = false; }  if(GUI.Button(Rect(70,160,100,20),"退出游戏")){  Application.Quit(); } GUI.DragWindow(new Rect(0,0,1000,1000));}

    15. 菜单制作方法

          1) GUITexture

          2) GUI对象:GUI.Window和GUISkin。


















               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    展开全文
  • 其实这个问题很简单,我认为可行的方法只有一种,就是获取脚本文件,然后把enable属性设置为true或者false就行了(ps:脚本文件可以堪称一个控件)。  c#:GameObject.Find("ObjectName").GetComponent().enabled=...

      这个问题已经是我第三次在网上查资料了,同样的问题应该重复查询说明使用频率很高,就有理由应该记住。其实这个问题很简单,我认为可行的方法只有一种,就是获取脚本文件,然后把enable属性设置为true或者false就行了(ps:脚本文件可以堪称一个控件)。
      c#:

    GameObject.Find("ObjectName").GetComponent<scriptName>().enabled=true/false;

      javascript:
      

    GameObject.Find("ObjectName").GetComponent(scriptname).enabled=true/false;
    展开全文
  • unity3d脚本编程

    2013-08-31 11:45:33
    一 创建和使用脚本 1 概述 GameObject的行为都是被...在unity中创建一个脚本,默认内容如下: using UnityEngine; using System.Collections; public class MainPlayer : MonoBehaviour { // Use this for initiali
    
    

    一 创建和使用脚本

    1 概述

    GameObject的行为都是被附加到其上面的组件控制,脚本本质上也是一个组件。

    在unity中创建一个脚本,默认内容如下:

    using UnityEngine;
    using System.Collections;
    
    public class MainPlayer : MonoBehaviour {
    
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
    }



    一个脚本通过实现一个派生自”MonoBehaviour”的类来与unity的内部工作机制建立联系。可以将新创建的组件类型的类作为一个蓝图,该类作为一个新类型的组件被附加到游戏对象。每次将一个脚本组件附加到游戏对象,都会创建一个该蓝图定义的对象的实例。创建的脚本文件的文件名必须与里面的类名相同,这样才能将其附加到游戏对象上。


    需要注意到的主要事情是,该类中定义的两个函数。Update函数处理游戏对象的帧更新相关的操作。这个可能包括移动,触发动作以及对用户输入的反馈,基本上在游戏过程期间需要处理的任何事情都可以在这里面处理。Start函数在游戏开始前被unity调用(例如,在Update被第一次调用之前),因而是一个进行初始化操作的理想位置。


    可能会疑惑为什么不把初始化操作放在类的构造函数中,这是因为对象的构造是由编辑器处理的,在游戏开始的时候并不如想象中那样会发生。如果为一个脚本组件定义构造器,它会和unity的正常操作发生干扰从而导致一些问题。


    脚本被创建之后是处于不激活状态的,只有将它的一个实例附加到一个游戏对象之后代码才会被激活。同时,一个游戏对象的一个类型的组件只能有一个,也就是可以附加到游戏对象的脚本组件不能超过一个。


    2 变量

    就是指的类的成员变量,只不过在unity这里将成员变量设为公有的时候,将其附加到游戏对象后,可以在游戏对象的监视面板中的脚本组件那栏里面看到该公有变量,也就是说可以在编辑器里面直接对该公有变量进行赋值,同时在debug状态下也可以在面板中看到它的值。

    unity在编辑器中显示类的成员变量的时候,在类名中遇到(不是第一个字母的)大写字母的时候,会在该字母前加入一个空格,例如在类里面定义个公有成员变量名为”TestVar”,在编辑器中显示的变量名为”Test Var”,中间加了一个空格,但是这只是一个unity显示变量的方式,真正在代码中访问这个变量仍然应该使用”TestVar”这个名字。


    3 事件函数

    unity中的脚本并不像传统意义上的程序,即在一个循环中连续的运行直到完成任务后再退出,而是unity通过调用定义在脚本内的某个函数,间断的将控制权交给一个脚本。一旦一个函数完成执行,控制权被交还给unity。这些函数就是所知的事件函数,因为它们由unity调用用于响应发生在游戏过程中的事件。unity支持的所有事件都定义在MonoBehaviour这个里面,可以在该类的参考文档中看到一系列的事件。下面介绍几个最常见、最重要的事件。

    <1> 常规更新事件(Regular Update Events)

    一个游戏更像一个在线生成动画帧的动画。游戏编程中的一个关键观念就是在每帧渲染前对游戏对象的位置、状态和行为进行改变。Update函数是unity中放置这类代码的主要地方,它在每帧被渲染前、同时也在动画被计算前调用。

    update事件函数

    void Update() {
    float distance = speed * Time.deltaTime * Input.GetAxis("Horizontal");
    transform.Translate(Vector3.right * speed);
    }

    物体引擎也以一个和帧渲染类似的方式每隔一个离散时间段进行更新。另一个叫FixedUpdate的函数在每次物理更新之前调用。由于物理更新和帧更新并不使用相同的频率更新,如果将上面的代码放到FixedUpdate函数而不是Update函数的话,可以得到更加精确的结果(FixedUpdate会以一个比Update更加稳定的帧率运行)。

    void FixedUpdate() {
    Vector3 force = transform.forward * driveForce * Input.GetAxis("Vertical");
    rigidbody.AddForce(force);
    }

    同时在场景中所有对象的Update和FixedUpdate调用之后,以及所有的动画计算之后仍然可能有需要进行一些额外的改变。一个例子就是在一个摄像头需要监视一个目标对象的时候,对摄像机朝向的调整必须在目标对象已经移动之后。另一个例子是在在需要用脚本代码来覆盖动画效果的场合(比如,使角色的头看向场景中的目标对象)。LateUpdate函数可以用于这些场合。


    <2>  初始化事件

    在游戏中的任何更新函数之前调用初始化代码是经常用到的,初始化函数Start在物体的第一帧更新或者物理更新之前被调用。Awake函数在场景被加载的时候,场景中的每个对象上的该函数都会被调用,所有的Awake函数都会在第一个Start函数(有好多对象的话就有好多个Start函数)调用之前被调用。这就意味着Start函数中的代码也可以使用发生在Awake阶段里面的初始化后的数据。


    <3> GUI事件

    unity有一个用于渲染GUI控件的系统,这些GUI控件处于场景之上并且响应鼠标事件。这个代码处理起来和常规的帧更新有些不大一样,因而它需要放到OnGUI函数中,周期性的被调用。

    void OnGUI() {
    GUI.Label(labelRect, "Game Over");
    }

    同时当发生鼠标单击场景中的游戏对象的时候可以检测这些消息。这个可以用于调整武器或者显示当前在鼠标下面的角色信息。一系列的OnMouseXXX事件函数可以用于和用户的鼠标行为交互。


    <4>物理事件

    物理引擎会通过调用物体上的事件函数来报告发生的与另一物体的碰撞事件。OnCollisionEnter、OnCollisionStay和OnCollisionExit函数分别在刚接触,持续和离开(broken)的时候调用。当碰撞器被配置成触发器的时候发生碰撞后对应的OnCollisionEnter、OnCollisionStay和OnCollisionExit会被调用。假如在物理更新期间有多于一个接触被检测到这些函数可能会被多次按顺序调用(即调用完一轮再来一轮)。


    二 控制游戏对象


    在unity中,可以在监视器面板中修改物体的组件属性,但是更多的时候,需要使用脚本来进行这些操作。


    1 访问组件

    最常见的一个情形是需要使用脚本访问附加到相同游戏对象上的另一个组件(当前脚本就是一个组件,其他的组件也就是另一个组件了)。在引言中提到过,一个组件实质上是一个类的实例,因而首先需要做的是获取想要操作的组件实例的引用。这个通过GetComponent函数来实现。典型的,可能会想要将一个组件赋值给一个变量,如下代码所示

    void Start () {
    Rigidbody rb = GetComponent<Rigidbody>();
    }

    一旦获取了组件实例的引用,就可以对它的属性进行想要的操作,同时也可以调用它之上的一些功能函数。

    如果想要访问另一个的脚本文件,也可以使用GetComponent,只需使用脚本的类名作为该函数的组件类型参数(因为脚本本来就也是一个组件)。

    如果想要去获取一个并没有添加到当前游戏对象的组件,GetComponent函数会返回null,如果试图去改变一个null对象上的任何值,将会发生null引用错误。

    由于一些组件类型经常使用,unity提供了一些内置的变量来访问它们,例如可以使用下面的代码

    void Start () {
    transform.position = Vector3.zero;
    }


    而不用使用GetComponent去获得Transform组件,所有的内置组件变量列表在MonoBehaviour类的参考手册里面有。


    2 访问其他对象

    虽然游戏对象有的时候都是各自处理,使用代码进行跟踪其他物体是常有的事。例如,一个追赶的敌人可能需要知道玩家的位置,unity提供了一系列不同的方法来获取其他对象,各适合不同的场合。


    <1> 将对象链接到变量

    最直接的办法是将一个游戏对象添加到脚本的公有成员变量上,直接在编辑器中将需要访问的游戏对象拖到对应脚本组件的那个公有成员变量上,unity会自动根据变量的类型将添加的游戏对象中相同的组件类型映射到该变量。

    例如将一个游戏对象拖给一个Transform的成员变量,就会自动的将游戏对象的Transform组件和该变量映射起来。

    直接将对象和变量链接起来在处理需要有永久链接的对象的时候是最有用的方法。同时也可以使用一个数组变量和几个相同类型的对象链接起来,但是这种链接必须在unity编辑器中完成,而不能在运行时进行。通常使用下面的两种方法来在运行时定位对象。


    <2> 查找子物体

    有的时候,一个游戏场景中可能会用到很多同一类型的对象,例如敌人、路点(waypoints)和障碍物。这些对象在游戏中需要由一个特定的脚本来监视和响应。这个时候使用变量来链接这些对象太过麻烦不好操作。对于这种情况,通常更好的方法是将一系列的对象添加到一个父对象下面,这些子对象可以通过使用父对象的Transfrom组件来获得。

    public class WaypointManager : MonoBehaviour {
    public Transform waypoints;
    
    void Start() {
    waypoints = new Transform[transform.childCount];
    int i = 0;
    
    for (Transform t in transform) {
    waypoints[i++] = t;
    }
    }
    }



    同时也可以使用Tranfrom.Find来查找某个具体的子对象。使用Transform来进行对象查找操作是因为每一个游戏对象都有Transfrom组件。


    <3> 通过名称或标签访问对象

    只要有一些信息,在层级场景中的任何位置定位到该游戏对象是可能的。单个对象可以通过GameObject.Find函数进行查找。如下:

    GameObject player;

    void Start() {
    player = GameObject.Find("MainHeroCharacter");
    }


    某个对象或者一系列的对象也可以分别通过GameObject.FindWithTag和GameObject.FindObjectsWidthTag函数进行定位。


    <4>查找特定类型的对象

    staticObjectFindObjectOfType(Type type)

    返回指定类型对象中的第一个活动的加载对象

    需要注意的是这个函数很慢(可能是由于要在整个场景中进行遍历),不推荐每一帧都使用这个函数,在大多数情况下可以使用单件模式

    例如

    Camera cam = FindObjectOfType(typeof(Camera)) as Camera;

    由于该函数返回的类型是Object,所以需要使用as进行一下强制转换。


    static Object[] FindObjectsOfType(Type type);

    返回指定类型的加载活动对象的列表,速度也慢

    HingeJoint[] hinges = FindObjectsOfType(typeof(HingeJoint)) as HingeJoint[];



    三 创建和销毁对象

    在运行时创建和销毁对象是常有的事。在unity中,可以使用Instantiate函数对现有的一个对象做一个拷贝来创建一个新的游戏对象。

    public GameObject enemy;

    void Start() {
    for (int i = 0; i < 5; i++) {
    Instantiate(enemy);
    }
    }

    值得注意的是用于进行拷贝的对象并不一定需要放置在场景中。更普遍的做法是将一个预设(Prefab)拖到脚本的对应公有成员变量上,实例化的时候直接对这个成员变量进行实例化即可。


    同时也有一个Destroy函数在帧更新函数完成后或设定的一个延时时间后销毁一个对象。

    void OnCollisionEnter(otherObj: Collision) {
    if (otherObj == "Missile") {
    Destroy(gameObject,.5f);
    }
    }

    注意到Destroy函数可以销毁单独的组件而不对游戏对象本身产生影响,一个通常范的错误是

    Destroy(this);

    这句代码仅仅效果脚本组件,而不会销毁该脚本所附加在的对象


    四 协程(Coroutines)

    当调用一个函数的时候,它会在返回前运行到结束位置。

    根据前面的知识可以知道,几乎所有的函数都由unity在帧更新的时候调用一次,然后到下一帧后再调用一次,那这个时候在函数中写一些循环体类的代码想要达到产生动画的效果可能会失败。如下

    void Fade() {
    for (float f = 1f; f <= 0; f -= 0.1f) {
    Color c = renderer.material.color;
    c.alpha = f;
    renderer.material.color = c;
    }
    }


    这是想要产生一个透明渐变的效果,但是由于Fade函数会在一个frame update时间片中全部执行完,达不到渐变效果。要达到这个效果,可以在帧更新函数中进行处理即可。但是,对于这类情形更方便的做法是使用coroutine。

    一个coroutine就像一个可以暂停执行并将控制权返回给unity的函数,但是在下一帧的时候又可以在它停止的位置继续执行。在C#中,这样声明一个coroutine:

    IEnumerator Fade() {
    for (float f = 1f; f <= 0; f -= 0.1f) {
    Color c = renderer.material.color;
    c.alpha = f;
    renderer.material.color = c;
    yield return;
    }
    }


    实质上它是一个返回类型为IEnumerator的函数,同时在函数体中增加了yield return这句代码。yield return这行就是会在执行的时候暂停、在下一帧的时候恢复执行的位置。要启动coroutine,需要使用StartCorutine函数。

    void Update() {
    if (Input.GetKeyDown("f")) {
    StartCoroutine("Fade");
    }
    }


    默认的情况下,一个coroutine在它暂停后的下一帧恢复,但是也可以使用WaitFroSeconds来引入一个延时。

    IEnumerator Fade() {
    for (float f = 1f; f <= 0; f -= 0.1f) {
    Color c = renderer.material.color;
    c.alpha = f;
    renderer.material.color = c;
    yield return new WaitForSeconds(.1f);
    }
    }


    这个可以用于产生一个随时间变化的效果,同时也是一个用于进行优化的有效方法。游戏中的许多人物需要周期性的执行,最常用的做法是将它们包含在Update函数中。但是Update函数通常每秒会调用多次。当有的任务并不需要这么频繁的被调用的时候,可以将它放在一个coroutine中按一定时间进行调用,而不是每一帧都调用。一个这样的例子就是用于在游戏中如果有敌人接近的话就提示玩家,代码如下

    function ProximityCheck() {
    for (int i = 0; i < enemies.Length; i++) {
    if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
    return true;
    }
    }
    
    return false;
    }
    IEnumerator DoCheck() {
    for(;;) {
    ProximityCheck;
    yield return new WaitForSeconds(.1f);
    }
    }


    当有很多敌人的时候,使用coroutine0.1秒执行一次靠近检查,可以减少大量的计算量。


    展开全文
  • Unity3D 之 2D 射击脚本 借用Unity 自带的项目, 做了个简单的射击脚本。成功实现,武器发送子弹以及子弹碰撞后销毁 过程。o( ̄▽ ̄)d~编译环境:Win10 + Unity 5.5.1f首先,在Unity 自带项目工程里,新建一个空对象...

    Unity3D 之 2D 射击脚本

    借用Unity 自带的项目, 做了个简单的射击脚本。成功实现了 武器发送子弹以及子弹碰撞后销毁 过程。o( ̄▽ ̄)d~

    编译环境:Win10 + Unity 5.5.1f

    首先,在Unity 自带项目工程里,新建一个空对象,命名为FirePoint 作为 射击的发射枪口。

    这里写图片描述

    然后新建一个脚本,实现射击与碰撞销毁。
    射击脚本的检测面板如下:
    这里写图片描述

    (预制武器物体 就自己弄了哈~)

    代码如下(C#脚本,亲测可行):

    
        // 变量定义
        public GameObject arrow;   // 弓箭 -- 预设物体
        public GameObject bullet;  // 子弹 -- 预设物体
        public Transform firePoint;// 发射点(枪口) -- 新建空gameObject,置放于发射枪口,然后拖进脚本即可
    
        private GameObject weapon; // 私有化 武器,用于切换武器装备
    
        public int speed = 100; // 初始化武器速度
    
        private string str = "发射次数:";
        private int count = 0;
        GUISkin guiskin;
    
    // 文本显示
    void OnGUI(){
        GUI.skin = guiSkin;
        GUI.color = Color.white;
        GUI.Label(new Rect(20,20, 100, 300), str);
    }
    
    void Start(){
        weapon = bullet; // 初始化 弓箭为攻击武器
    }
    
    
    void Update(){
    
            if (Input.GetButtonDown("Fire1") )
            {
                //GameObject clone = Instantiate(bullet, this.transform.position, this.transform.rotation); // 以当前对象 为发射点
    
                // 实例化 clone ,让它 与发射点的方向 保持一致。
                GameObject clone = Instantiate(weapon, firePoint.position, firePoint.rotation);  //以枪口为发射点,
                clone.GetComponent<Rigidbody2D>().velocity = transform.TransformDirection(Vector3.right * speed); // 根据发射口 ,判断发射方向,3D 用 Vector3.forward
    
                count++;
            }
    
            // 武器切换,并更改武器发射速度
            if (Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.Q))
            {
                Debug.Log("Replace the weapon.");
                weapon = (weapon == arrow) ? bullet : arrow; // 切换武器
                speed = (weapon == arrow) ? 80 : 100;
            }
    }
    
    // 武器射击后 碰撞销毁 (3D 用OnCollisionEnter()方法 )
    // 也可以把下面代码单独写进 一个脚本,然后绑定预制武器的预制武器即可。
    void OnCollisionEnter2D(){
        Destory(weapon);
    }
    

    嗯,先写到这里吧,里面也有注释了。╰( ̄▽ ̄)╭

    展开全文
  • 使用C#脚本控制游戏对象,是一项必备的基本技能。Unity3D可以使用的脚本有C#和javascript等。我们主要讲注意力集中在C#上。本文将会介绍怎样使用脚本控制场景中的游戏对象。

    前言

    使用C#脚本控制游戏对象,是一项必备的基本技能。Unity3D可以使用的脚本有C#和javascript等。我们主要讲注意力集中在C#上。本文将会介绍怎样使用脚本控制场景中的游戏对象。

     

    1 创建脚本

    点击Project视图中的Create——C# Script。然后将脚本命名为motion.cs。双击脚本,使用编辑器打开它。我的编辑器已经改为了VS2013,软件默认的编辑器是MonoDevelop。默认的内容如下。

    using UnityEngine;
    using System.Collections;
    
    public class motion : MonoBehaviour {
    
    	// Use this for initialization
    	void Start () {
    	
    	}
    	
    	// Update is called once per frame
    	void Update () {
    		
    	}
    }

    首先,using关键字定义了两个默认使用的程序集UnityEngine和System.Collections。然后类名和我们定义的文件名保持一致。类里面有两个默认的函数Start()和Update()。Start()在脚本运行开始时执行,而Update()在游戏运行的每一帧都执行。

     

    2 控制方块运动

    我们创建一个Cube,然后使用自己写的脚本控制其运动。假设场景中已经有了一个Cube,为了使我们的C#脚本可以随着游戏开始而运行,我们需要将脚本绑定在Hierarchy中的某个物体上。不妨我们就把脚本绑定在方块上吧。绑定脚本的方式很简单,直接用鼠标把脚本拖动到Hierarchy视图或者Scene视图中对应的物体上即可。也可以先选中物体,然后把脚本拖动到该物体Inspector视图的空白处。

    在脚本的Start()函数中添加这句话:

    Debug.Log("hello unity");

    然后点击游戏运行按钮,可以在控制台窗口看到如下信息,表示脚本运行成功。


    接下来我们使用脚本控制方块的旋转、平移、缩放。

    (1)旋转

    this.transform.Rotate(Vector3.up*1,Space.World);

    将上面的语句写到Update函数中,表示每一帧沿着世界坐标系的Y方向旋转1度。如果要沿着自身坐标系,则将Space.World改为Space.Self.

    this.transform.Rotate(Vector3.up*1,Space.Self);


    (2)平移

    this.transform.Translate(Vector3.up*0.1f,Space.World);

    将上面的语句写到Update函数中,表示每一帧沿着世界坐标系的Y方向移动0.1m。Unity默认的长度单位是米。如果要沿着自身坐标系,则将Space.World改为Space.Self.

    this.transform.Translate(Vector3.up*0.1f,Space.Self);


    (3)缩放

    this.transform.localScale = new Vector3(1 +Mathf.Sin(Time.time), 1 + Mathf.Sin(Time.time), 1 + Mathf.Sin(Time.time));

    将上面的语句写到Update函数中,该语句可以使得方块随着时间做正弦运动规律的缩放。

     

    3 控制多个对象

    前面我们在控制对象的时候,使用了“this”,它指的是脚本被绑定的那个物体。如果我们要控制多个物体,就需要使用公有变量绑定物体或使用脚本动态寻找物体。

    在场景中创建3个Cube,分别是Cube1,Cube2,Cube3。将写好的脚本绑定到摄像机上。


    (1)使用公有变量

    将脚本内容设置为如下所示。

    using UnityEngine;
    using System.Collections;
    
    public class motion : MonoBehaviour {
    
    	public GameObject cube1;
        public GameObject cube2;
        public GameObject cube3;
    
    	void Start () {
            Debug.Log("hello unity");
    	}
    	
    	// Update is called once per frame
    	void Update () {
            cube1.transform.Translate(Vector3.up*0.1f, Space.World);
            cube2.transform.Rotate(Vector3.up*1,Space.Self);
            cube3.transform.localScale = new Vector3(1 + Mathf.Sin(Time.time), 1 + Mathf.Sin(Time.time), 1 + Mathf.Sin(Time.time));
    	}
    }


    拖动对应的Cube到脚本的变量上。



    (2)使用脚本动态绑定

    如果使用脚本自动绑定物体,则使用下面的脚本。

    using UnityEngine;
    using System.Collections;
    
    public class motion : MonoBehaviour
    {
    
        GameObject cube1;
        GameObject cube2;
        GameObject cube3;
    
        void Start()
        {
            cube1 = GameObject.Find("Cube1");
            cube2 = GameObject.Find("Cube2");
            cube3 = GameObject.Find("Cube3");
        }
    
        // Update is called once per frame
        void Update()
        {
            cube1.transform.Translate(Vector3.up * 0.1f, Space.World);
            cube2.transform.Rotate(Vector3.up * 1, Space.Self);
            cube3.transform.localScale = new Vector3(1 + Mathf.Sin(Time.time), 1 + Mathf.Sin(Time.time), 1 + Mathf.Sin(Time.time));
        }
    }

    (3)运行效果如下图



    展开全文
  • Unity3D的基本操作很容易就能掌握了,接下来就是游戏系统的核心部分:脚本。 什么是Script(脚本)?简而言之,就是使用代码来执行一系列动作命令的特殊文本,它需要编译器来从新解读。U3D内部如何解读脚本,这...
  • unity3d动态加载脚本

    2014-09-15 11:01:17
    本文记录如何通过unity3d进行脚本资源打包加载 1、创建TestDll.cs文件 public class TestDll : MonoBehaviour {  void Start () {  print("Hi U_tansuo!");  } } 2、生成dll文件  (1)使用vs...
  • unity3D禁用脚本

    2019-04-11 19:45:19
    如果想直接使用enabled来禁用脚本或者组件,必须继承至MonoBehaviour camera.enabled = false; C#: GetComponent().enabled = true; 如果不是继承MonoBehaviour的做法: (gameObject.GetComponent(“MyScript”) as...
  • 尽管Unity有一个像样的脚本编辑器(Mono),但很多人喜欢使用另一个编辑器。这篇短文解释了如何更改脚本编辑器,并介绍了Mono的一些替代方案。 二、默认脚本编辑器:mono 如果您想知道脚本编辑器是什么:在双击脚本时...
  • Unity3D Editor 编辑器扩展3 Editor脚本环境:Unity2017.2 语言:C# 总起:在编辑Unity项目的时候,总不可能避免的接触到Unity自身自带的Inspector参数调整无法很好的完成某些特定功能的情况。 比方说想要一个...
  • Unity3D脚本手册

    2016-05-07 00:37:39
    翻译:脚本_树 This is a short overview of how scripting inside Unity works. Scripting inside Unity consists of attaching custom script objects called behaviours to game objects. Different ...
  • 摘要:《Unity 3D脚本编程——使用C#语言开发跨平台游戏》由枫叶小屋(www.fy29.top)发布。...作者信息:陈嘉栋长期关注Unity3D、Mono以及C#语言,并且在博客园、游戏蛮牛以及InfoQ网站以“慕容小匹夫...
  • unity3d中如何为动画添加脚本 目的:达到手动控制一个立方体运动或停止
  • VS2017 调试 Unity3D 脚本

    2018-05-29 16:15:55
    1. 安装Unity3D最新版本. https://unity3d.com/cn/get-unity/download2. 安装Visual Studio Community 2017. https://www.visualstudio.com/zh-hans/downloads/这里有 Community, Professional, Enterprise, 个人...
  • Unity3D的基本操作很容易就能掌握了,接下来就是游戏系统的核心部分:脚本。 什么是Script(脚本)?简而言之,就是使用代码来执行一系列动作命令的特殊文本,它需要编译器来从新解读。U3D内部如何解读脚本,这不是...
  • Unity3D _脚本之间通信

    2017-12-19 10:41:05
    1.利用在脚本A中定义对外接口函数,然后在脚本B中找到A所在的对象,再找到脚本A,进而调用里面的对外接口函数,这个方法在我的《unity3D NGUI中button响应事件实现》这篇文章中有仔细说明,可以参考。 2.还有一个是...
  • 代码规范 代码规范问题是这样的一个问题:高性价比,不被重视,实际做的时候难以做好 ...大家都会说需要有一个统一的规范,但是实际做起来,还是容易各做各的 实际上能遵从统一的代码规范,我在职业生涯里还没有遇到做的特别...
  • Unity3D利用代码生成脚本模板 目录 1、博客介绍 2、内容 (1)生成脚本展示 (2)核心 3、推送 4、结语 1、博客介绍 最近一直在学习框架,看到了一点关于在编辑器下去自动生成UI相关代码的逻辑,感觉很好...
  • 使用unity3d 开发时,需要通过vs 这样的ide 去编写具体的代码,但是双击脚本后,unity3d 总是提示 vs2010 shell 认证无效,很是纳闷,我装的是2017为什么去找vs2010,后来通过测试发现,需要在unity3d里面关联编辑脚本的...
1 2 3 4 5 ... 20
收藏数 33,010
精华内容 13,204