Scorpio-CSharp——第一弹 Space Shooter

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scorpio-CSharp——第一弹 Space Shooter相关的知识,希望对你有一定的参考价值。

  写在前面————

        哈哈, 开始做关于脚本热更新的第一个例子了,鉴于本人还是个没毕业的学生,所以不足之处还希望大家包涵~~~~~~

 

 

  注意:

          1.本文章是用Space Shooter(Unity3d官方的小游戏)做的例子

          2.Space Shooter源码和Scorpio-CSharp 的下载链接我会放在文章最后面

          3.如有任何疑问,请加群245199668

 

 

  正文

          1.新建项目,把下载好的Space Shooter导入Unity中, 打开Done_Main场景, 

                           技术分享

 

           2.下载Scorpio-CSharp,你会得到几个文件:Scorpio,ScorpioDemo,ScorpioExec,ScorpioMaker,ScorpioTest。把Scorpio整个文件夹复制到      Unity3d里(如果还不知道Scorpio-CSharp是什么或者是热更新是什么请点这里这里)。

          3.做一个底层。新建2个脚本,ActionManager和ScriptComponent。ActionManager主要是提供一些方法方便调用,而ScriptComponent是为了过渡C#               脚本,或者也可以说是从C#到Scorpio-CSharp的一个接口。而运行一个Scorpio-CSharp脚本需要压入程序集(PushAssembly)和导入类(import_type)

Singleton:方便全局调用

1 //单例模式
2 public abstract class Singleton<T> where T : class, new()
3 {
4     static T msInstance = null;
5     public static T Instance { get { return msInstance ?? (msInstance = new T()); } }
6 }

 ActionManager:

      1.它可以随时随地运行一个热更新脚本,但是该脚本挂载的ScriptComponent是摄像机的,也就是说this.gameObject获得的是摄像机的,OnTriggerEnter之类的函数也是摄像机。

      2.它也可以通过RunScript运行指定物体上的热更新脚本

注意,所有的热更新脚本已通过ActionManager把常用类导入进去了且都放在了Resources文件夹下,通过Resources.Load读取。

 1 #define DEBUG
 2 
 3 using UnityEngine;
 4 using System .Collections;
 5 using Scorpio;
 6 
 7 public class ActionScriptManager : Singleton<ActionScriptManager>
 8 {
 9     public ActionScriptManager ( )
10     {
11         script = new Script ( );
12         ScriptComponent sc = Camera.main.gameObject.AddComponent<ScriptComponent>();
13         sc .Init ( script );
14         try
15         {
16             SetScript ( script );
17             
18             importType = Resources .Load ( "ImportType" ) as TextAsset;
19         }
20         catch ( System .Exception e )
21         {
22             Debug .LogError ( "StackInfo : " + script .GetStackInfo ( ) );
23             Debug .LogError ( e .ToString ( ) );
24         }
25 #if DEBUG
26         stopwatch = new System .Diagnostics .Stopwatch ( );
27 #endif
28     }
29 
30     public void SetScript(Script scriptTmp)
31     {
32         if(scriptTmp != null)
33         {
34             scriptTmp .LoadLibrary ( );
35             scriptTmp .PushAssembly ( GetType ( ) .Assembly );
36             //system
37             scriptTmp .PushAssembly ( typeof ( byte ) .Assembly );
38             //UnityEngine
39             scriptTmp .PushAssembly ( typeof ( Object ) .Assembly );
40         }
41     }
42 
43     public ScriptObject RunScript ( string scoName )
44     {
45         return RunScript ( script , scoName );
46     }
47 
48     public ScriptObject RunScript ( Script scriptTmp, string scoName )
49     {
50         ScriptObject ret;
51 
52         if(scriptTmp == null)
53         {
54             Debug .LogError ( scriptTmp + " is null" );
55             return null;
56         }
57 
58         textAsset = Resources .Load ( scoName ) as TextAsset;
59         if(textAsset == null)
60         {
61             Debug .LogError ( scoName + " is null" );
62             return null;
63         }
64 
65         targetText = importType .text;
66         targetText += textAsset .text;
67 
68 #if DEBUG
69         stopwatch .Start ( );
70 #endif
71         
72         ret = scriptTmp .LoadString ( targetText );
73 
74 #if DEBUG
75         stopwatch .Stop ( );
76         Debug .Log ( scoName + " 运行时间: " + stopwatch .ElapsedMilliseconds .ToString ( ) + "ms" );
77 #endif
78 
79         return ret;
80     }
81 
82     //脚本源文件
83     TextAsset textAsset;
84     //注册
85     TextAsset importType;
86     //目标字符串
87     string targetText;
88     //热更新脚本
89     Script script;
90 #if DEBUG
91     //计时器
92     System.Diagnostics.Stopwatch stopwatch;
93 #endif
94 }

ScriptComponent:

 1 using UnityEngine;
 2 using Scorpio;
 3 
 4 public class ScriptComponent : MonoBehaviour
 5 {
 6     public Script script;
 7     public ScriptTable scriptTable;
 8 
 9     public void Init(Script source)
10     {
11         script = source;
12         scriptTable = source .GetGlobalTable ( );
13         scriptTable .SetValue ( "transform" , script .CreateUserdata ( this .transform ) );
14         scriptTable .SetValue ( "gameObject" , script .CreateUserdata ( this .gameObject ) );
15         OnStart ( );
16     }
17 
18     void OnStart()
19     {
20         Call ( "Awake" );
21     }
22 
23     void Start()
24     {
25         Call ( "Start" );
26     }
27 
28     void Update()
29     {
30         Call ( "Update" );
31     }
32 
33     void FixedUpdate()
34     {
35         Call ( "FixedUpdate" );
36     }
37 
38     void OnGUI ( )
39     {
40         Call ( "OnGUI" );
41     }
42 
43     void OnCollisionEnter ( Collision otherCollider )
44     {
45         Call ( "OnCollisionEnter" , otherCollider );
46     }
47 
48     void OnCollisionStay ( Collision otherCollider )
49     {
50         Call ( "OnCollisionStay" , otherCollider );
51     }
52 
53     void OnCollisionExit ( Collision otherCollider )
54     {
55         Call ( "OnCollisionExit" , otherCollider );
56     }
57 
58     void OnTriggerEnter ( Collider otherCollider )
59     {
60         Call ( "OnTriggerEnter" , otherCollider );
61     }
62 
63     void OnTriggerStay ( Collider otherCollider )
64     {
65         Call ( "OnTriggerStay" , otherCollider );
66     }
67 
68     void OnTriggerExit ( Collider otherCollider )
69     {
70         Call ( "OnTriggerStay" , otherCollider );
71     }
72 
73     public void Call(string func, params object[] args)
74     {
75         if(scriptTable != null && scriptTable.HasValue(func))
76         {
77             ( ( ScriptFunction ) scriptTable .GetValue ( func ) ) .call ( args );
78         }
79     }
80 }

ImportType:

 1 //UnityEngine
 2 GameObject = import_type("UnityEngine.GameObject")
 3 Object = import_type("UnityEngine.Object")
 4 Mathf = import_type("UnityEngine.Mathf")
 5 PrimitiveType = import_type("UnityEngine.PrimitiveType")
 6 Resources = import_type("UnityEngine.Resources")
 7 Debug = import_type("UnityEngine.Debug")
 8 Transform = import_type("UnityEngine.Transform")
 9 Vector2 = import_type("UnityEngine.Vector2")
10 Vector3 = import_type("UnityEngine.Vector3")
11 Vector4 = import_type("UnityEngine.Vector4")
12 Application = import_type("UnityEngine.Application")
13 Time = import_type("UnityEngine.Time")
14 Camera = import_type("UnityEngine.Camera")
15 LineRenderer = import_type("UnityEngine.LineRenderer")
16 Screen = import_type("UnityEngine.Screen")
17 SleepTimeout = import_type("UnityEngine.SleepTimeout")
18 Input = import_type("UnityEngine.Input")
19 SpriteRenderer = import_type("UnityEngine.SpriteRenderer")
20 KeyCode = import_type("UnityEngine.KeyCode")
21 Color = import_type("UnityEngine.Color")
22 Random = import_type("UnityEngine.Random")
23 Quaternion = import_type("UnityEngine.Quaternion")
24 Animator = import_type ("UnityEngine.Animator")
25 Renderer = import_type ("UnityEngine.Renderer")
26 Collision = import_type("UnityEngine.Collision")
27 Audiosource = import_type("UnityEngine.AudioSource")
28 Rigidbody = import_type("UnityEngine.Rigidbody")
29 //System
30 byte = import_type("System.byte")
31 int = import_type("System.Int32")
32 float = import_type("System.Single")
33 double = import_type("System.Double")
34 bool = import_type("System.Boolean")
35 string = import_type("System.string")
36 
37 List = import_type("System.Collections.Generic.List`1")
38 ListInt = generic_type(List, int)
39 ListGameObject = generic_type(List, GameObject)
40 
41 //Owner class
42 ActionScriptManager = import_type("ActionScriptManager")
43 ScriptComponent = import_type("ScriptComponent")
44 Script = import_type("Scorpio.Script")

         4.修改Done_PlayerController成热更新脚本,在Done_GameController脚本的Start函数中加入下面代码,修改类Done_Boundary,加入构造函数。

1 ScriptComponent sc = GameObject.FindGameObjectWithTag("Player").AddComponent<ScriptComponent>();
2 Script s = new Script();
3 sc .Init ( s );
4 ActionScriptManager .Instance .SetScript ( s );
5 ActionScriptManager .Instance .RunScript ( s , "PlayerController" );

Done_PlayerController.txt:

 1 var speed = 10;
 2 var tilt = 5;
 3 var boundary = Done_Boundary(-6, 6, -4, 8);
 4 var shot;
 5 var shotSpawn;
 6 var fireRate = 0.25;
 7 var nextFire = 0;
 8 function Update ()
 9 {
10     shot = Resources.Load("Done_Bolt");
11     shotSpawn = transform.FindChild("Shot Spawn");
12     if (Input.GetButton("Fire1") && Time.time > nextFire) 
13     {
14         nextFire = Time.time + fireRate;
15         GameObject.Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
16         gameObject.GetComponent(typeof(AudioSource)).Play ();
17     }
18 }
19 function FixedUpdate()
20 {
21     var moveHorizontal = Input.GetAxis ("Horizontal");
22     var moveVertical = Input.GetAxis ("Vertical");
23     var movement = Vector3 (moveHorizontal, 0.0, moveVertical);
24     gameObject.GetComponent(typeof (Rigidbody)).velocity = Vector3.op_Multiply(movement, speed);
25     gameObject.GetComponent(typeof(Rigidbody)).position = Vector3
26     (
27         Mathf.Clamp (gameObject.GetComponent(typeof(Rigidbody)).position.x, boundary.xMin, boundary.xMax), 
28         0.0, 
29         Mathf.Clamp (gameObject.GetComponent(typeof(Rigidbody)).position.z, boundary.zMin, boundary.zMax)
30     );
31     gameObject.GetComponent(typeof (Rigidbody)).rotation
32         = Quaternion.Euler(0, 0, gameObject.GetComponent(typeof (Rigidbody)).velocity.x * -tilt);
33 }

 

今天就先到这里了。。。

 

————————————————————————————————华丽的分割线———————————————————————————————————————————————

 

 

  注意:

    1.假如在热更新脚本里使用系统或者unity的类,需先把程序集压入到Script里面(俩个类在同意程序集只用压一次), 然后再热更新脚本前头声明该类来自那个程序集(每个类都必须声明)。

如果说是自己写的类直接import_type和scriptTmp .PushAssembly ( GetType ( ) .Assembly );

例如(GameObject和Object在同一程序集里):

    scriptTmp .PushAssembly ( typeof ( Object ) .Assembly );

    GameObject = import_type("UnityEngine.GameObject")

    Object = import_type("UnityEngine.Object")

    2.Scorpio-CSharp脚本类似js脚本,声明全部用var

    3.默认数字为double和long,0为long,0.0为double

    4.没有new关键字,类初始化可以直接GameObject(),不需要new

    5.可以GetComponent(typeof(AudioSource)),不能GetComponent<AudioSource>()

    6.没有重写+=,-=,/=,*=操作符,可以通过Vector3.op_Multiply(乘),Vector3.op_Addition(加)实现

    7.热更新脚本没有继承mono使用创建和摧毁前得加上GameObject(GameObject.Destroy)

 

  链接:

    Space Shooter:     http://pan.baidu.com/s/1geuEEkF

    Scorpio-CSharp: https://github.com/qingfeng346/Scorpio-CSharp#showcase

    更多例子请看ScorpioDemo。

以上是关于Scorpio-CSharp——第一弹 Space Shooter的主要内容,如果未能解决你的问题,请参考以下文章

Scorpio-CSharp基础语法介绍 变量篇

Scorpio-CSharp总链接

第一弹

深入理解ThreadPoolExecutor第一弹

深入理解ThreadPoolExecutor第一弹

codechef 营养题 第一弹