當前位置:首頁 » 編程軟體 » unity條件編譯

unity條件編譯

發布時間: 2023-06-18 17:20:23

㈠ Unity3D開發中熱更新為什麼不能使用C#的思考

閱讀了網上一些文章,其實使用C#進行熱更新是可以的,將需要更新的代碼打包成程序集,然後利用反射即可,但是也提到在IOS平台是不行的,至於為什麼不行,就不再說了,然後就是推薦Lua作為熱更新方案,但是,為啥Lua就行?C#就不行?
因為C#是編譯型語言,Lua是解釋型語言?
好多人都說Lua能熱更新,是因為它是解釋型語言,不用編譯,在運行時能動態解釋Lua代碼並運行。這種方法實際上不準確,從某些角度來說是錯的。Lua確實是解釋性腳本語言,但是不是因為是解釋型才能進行熱更新。即使使用C++這種編譯語言,也能進行熱更新,將動態鏈接庫進行更新就是,然後動態載入動態鏈接庫獲取更新的函數地址即可。
而且,還有一點,C#並不能說是一種編譯型語言,C#代碼會被編譯成IL,IL解釋成機器碼的過程可以在運行之前進行也能在運行時進行。如果在運行時進行解釋,那麼和Lua不就一樣了嗎,為啥C#不能進行熱更新呢?
JIT對IL進行解釋執行的原理
首先說一下,JIT對IL如何在運行時進行解釋並執行的,大致過程為:將IL解釋為所在平台的機器碼,開辟一段內存空間,要求這段內存空間可讀、可寫、可執行,然後把解釋出的機器碼放入,修改CPU中的指令指針寄存器中的地址,讓CPU執行之前解釋出來的機器碼。
注意這段內存的條件,最重要的一條是必須是可執行的,一般的內存申請我們只是存放數據,但是這里的內存許可權要是有可執行許可權
IOS限制了什麼?
IOS不允許獲取具有可執行許可權的內存空間,這就直接要求JIT要以full AOT模式,這種模式會在生成之前把IL直接翻譯成機器碼而不是在運行期間,進行了這種操作C#從某種角度來說和C++一樣,成為了編譯型語言,失去了運行時解釋的功能。
Lua的解釋執行怎麼就行呢?
如果Lua的解釋執行原理和C#相同,肯定也不能在IOS平台上運行時解釋執行。Lua是使用C編寫的腳本語言,它在運行時讀入Lua編寫的代碼,在解釋Lua位元組碼(Lua自己的指令)時不是翻譯為機器碼,而是使用C代碼進行解釋,不用開辟特殊的內存空間,也不會有新代碼在執行,執行的是Lua的虛擬機,用C寫出來的虛擬機,這和C#的機制是完全不同的,因為Lua是基於C的腳本語言。
總結
說白了,就是由於Lua這種腳本語言的特性,基於已經存在的某種語言的一種新的語言,這也是腳本語言和C#、C++這類語言的本質區別。當然,Lua虛擬機不僅可以使用C寫,也可以用C#寫。使用熱更新也不一定非要用Lua,Python同樣可以,只不過Lua短小精悍,本身代碼長度就不是很大,可以從GitHub上看到。

㈡ 手機游戲是用什麼開發的

手機游戲一般是用Unity、COCOS、java、C語言開發的,但也要看具體情況,有的手機游戲也可能是用HTML5開發的。

flash、java游戲俗稱小游戲,基本上都是一些休閑類的、傻呆萌的情節和操作,這類游戲開發相對比較簡單,會javascript、flash cs、java就可以進行開發了。

開發游戲我們經常聽到的是游戲引擎,一個游戲引擎決定一個游戲最基本的東西操作和效果,那麼一般的游戲開發架構從底到頂一般是Direct X游戲引擎。

Direct X可是大名鼎鼎相當於所有顯卡的一個統一介面,為游戲提供一個利用硬體渲染的編程模型,但Direct X介面為了追求高性能功能非常簡單基本的繪圖功能,不利於游戲的高效開發。

此時就需要根據游戲特點對其進行適當的取捨和封裝,實現一組更高抽象的游戲開發介面和框架,可以理解成游戲引擎中的圖形引擎。這部分的開發一般使用的語言是C、C++和少量的匯編語言。

㈢ unity shader里 dot(lightCoord, lightCoord).rr

#ifdef USING_DIRECTIONAL_LIGHT
fixed atten = 1.0;
#else
float3 lightCoord = mul(_LightMatrix0, float4(i.worldPos, 1)).xyz;
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#endif

  • _LightMatrix0:這個變數在書的P184頁表格和官方文檔中均有說明,它在內置的AutoLight.cginc文件中的特定宏下被定義,可以用於把點從世界空間變換到該光源的局部空間下。因此,上面代碼第一句「mul(_LightMatrix0, float4(i.worldPos, 1)).xyz」就是把頂點坐標變換到光源空間下的坐標,這點在書中也有解釋。

  • _LightTexture0:和_LightMatrix0類似的,也是在內置的AutoLight.cginc文件中的特定宏下被定義,緊跟_LightMatrix0的定義。它是一張包含了光源衰減信息的衰減紋理,我們可以用第一句代碼得到的坐標進一步處理得到衰減紋理的采樣坐標。由於Unity沒有官方解釋_LightMatrix0具體的數值范圍含義,我們可以推測得到(推測方法可以是利用假彩色一節的方法來把這個變數當成顏色輸出)_LightMatrix0得到的坐標模範圍會是[0, 1],即與光源重合處是(0, 0, 0), 在光源范圍的邊界處模值為1。而 dot(lightCoord, lightCoord).rr一句,首先是由點積得到光源的距離平方,這是一個標量,我們對這個變數進行.rr操作相當於構建了一個二維矢量,這個二維矢量每個分量的值都是這個標量值,由此得到一個二維采樣坐標。這個操作是shader中常見的swizzling操作,Cg的官網上也有說明。我們隨後使用這個二維坐標對光照衰減紋理_LightTexture0進行采樣,得到衰減值。關於_LightTexture0後面會系統講。

  • 這段代碼不夠規范:書上有說這一節的代碼不能直接用到項目里,僅僅是用來闡述原理,但如果你想用這段代碼直接發布項目的話,是需要修改的,因為當時寫的時候不夠規范。原因是這段代碼的keyword判斷條件有問題,導致_LightTexture0或_LightMatrix0可能並沒有被定義。我們可以將原來的代碼替換成下面的代碼(新的代碼也已經push到了github上):

    #ifdef USING_DIRECTIONAL_LIGHT
    fixed atten = 1.0;
    #else
    #if defined (POINT)
    // 把點坐標轉換到點光源的坐標空間中,_LightMatrix0由引擎代碼計算後傳遞到shader中,這里包含了對點光源范圍的計算,具體可參考Unity引擎源碼。經過_LightMatrix0變換後,在點光源中心處lightCoord為(0, 0, 0),在點光源的范圍邊緣處lightCoord模為1
    float3 lightCoord = mul(_LightMatrix0, float4(i.worldPos, 1)).xyz;
    // 使用點到光源中心距離的平方dot(lightCoord, lightCoord)構成二維采樣坐標,對衰減紋理_LightTexture0采樣。_LightTexture0紋理具體長什麼樣可以看後面的內容
    // UNITY_ATTEN_CHANNEL是衰減值所在的紋理通道,可以在內置的HLSLSupport.cginc文件中查看。一般PC和主機平台的話UNITY_ATTEN_CHANNEL是r通道,移動平台的話是a通道
    fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
    #elif defined (SPOT)
    // 把點坐標轉換到聚光燈的坐標空間中,_LightMatrix0由引擎代碼計算後傳遞到shader中,這裡麵包含了對聚光燈的范圍、角度的計算,具體可參考Unity引擎源碼。經過_LightMatrix0變換後,在聚光燈光源中心處或聚光燈范圍外的lightCoord為(0, 0, 0),在點光源的范圍邊緣處lightCoord模為1
    float4 lightCoord = mul(_LightMatrix0, float4(i.worldPos, 1));
    // 與點光源不同,由於聚光燈有更多的角度等要求,因此為了得到衰減值,除了需要對衰減紋理采樣外,還需要對聚光燈的范圍、張角和方向進行判斷
    // 此時衰減紋理存儲到了_LightTextureB0中,這張紋理和點光源中的_LightTexture0是等價的
    // 聚光燈的_LightTexture0存儲的不再是基於距離的衰減紋理,而是一張基於張角范圍的衰減紋理
    fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
    #else
    fixed atten = 1.0;
    #endif
    #endif

    上面更加精確地判斷了keyword條件,保證只在正確的時候執行訪問衰減紋理的代碼。_LightTexture0和_LightMatrix0隻在某些條件下會被定義,例如在開啟了POINT、SPOT、POINT_COOKIE、DIRECTIONAL_COOKIE等,具體我們可以在AutoLight.cginc裡面找到。但因為原來的代碼里沒有進行嚴格判斷,在發布的時候由於Unity會嚴格編譯Unity Shader根據不同的keyword生成對應的shader program,此時它就會發現我們的錯誤了。

㈣ 如何用unity3d編寫javascript

Unity中的JS,也稱UnityScript,和基於瀏覽器的JS有比較大的區別,因為UnityScript是基於Mono的.net 的IL語言規范,CLR運行環境(Mono虛擬機)上設計的語言。
0.基本概念:
Unity3d中的腳本可以與游戲對象鏈接,變數數值的修改以及實時預覽腳本修改後的游戲效果,節省了很多腳本調整和調試的時間,提高了開發效率。
簡單的項目和Unity中的大量例子和腳本資源包都是用JS。商業項目基本都用C#,因為C#和C/C++交互方便,豐富的數據結構和面向對象的架構利於大型程序的編寫,很多強大的第三方插件是用C#開發的,方便工作流程。
編譯過程:
UnityScript運行環境使用Mono 的.NET Framework。實際上,UnityScript是用Boo實現的,Boo是運行在Mono虛擬機上的一種語言,並且編譯成本機代碼。JavasScript很多典型的運行環境如String和Math庫由Mono提供。你也就知道了為什麼UnityScript中方法名要大寫了,因為要與Mono中相同。
Unity中的腳本和傳統的解釋型(JIT解釋)語言不同,都是需要經過編譯的,因此速度都一樣快。
這三種語言的代碼最後都會被編譯執行,而且腳本可以互相訪問。
庫的調用:
Unity的腳本基於Mono的.net平台上運行,腳本都可以使用.net庫,為xml,資料庫,正則表達式提供了良好的解決方案。
Unity中js想調用mono的.net庫,直接import即可。
import System;
import System.IO;
否則,你帶指定完整的命名空間來調用函數,如System.IO.File.Open(),而不是File.Open()。
1.基本類型和語句:
1)數據類型:
數值類型:char,byte,sbyte;short, ushort, int, uint, long, ulong; float,double; decimal.
布爾值:boolean
字元串:String,[index]符號
字元串[0]是字元串取下標為0的字元。
var s: String = "Whatever_it_may_be";
s =s.Replace("_"[0], " "[0]); // replace all the underscoreswith spaces
2)變數聲明:
變數必須先聲明[必須](編譯緣故,且聲明類型有利於減少太多常量,避免內存泄露發生),可以定義類型[可選]:
var playerName:String;
函數的參數也要聲明類型:
function Test( playerName:String, baseInfo:Object )
{
}
如果聲明時候定義或賦值了類型,那麼不能再改變類型,除非聲明時候不定義類型。
var a= "test";
a =5;// 報錯
var a;
a ="test";
a =5;//正確
變數前面可以加public,protected, private來修飾;不寫默認是public的,public的變數可以在Inspector視圖中查看和編輯。
3)數組:
內建自定義數組(快功能簡單):
var values : int[] = {1,2,3};
轉換到Array數組(需要對數組處理),var arr = new Array(values);
Array對象數組(慢動態增長排序合並功能):
var arr = new Array(); arr.Push("good");
轉換到內建數組(需要比較高的性能時候),var bArray : int[] = arr.ToBuiltin(int);
4)鏈表和泛型:
UnityScript可以使用泛型,所以當用到動態大小的數組時,最好用List來替代Array。基本上就沒有什麼理由要用到Array了,List更快並且功能更多。如果你需要混合類型的數組,你可以用Object List。UnityScript中泛型的語法與C#中接近,除了要加一個額外的「.」符號在「<>」之前。如C#中的"varmyList = new List<int>();"在UnityScript中對應的寫法為:"var myList = new List.<int>();"。
5)運算符和表達式:
和C一樣。
6)語句:
每行必須寫分號; 比C多了for in 用於遍歷對象元素,for(var i:int = 0; i < 10; i++)。
switch可以使用String變數。
2.函數
聲明規則:
function函數名(參數1:參數類型, 參數2:參數類型...):返回值類型
{
}
unityScript中的函數可以視為Function類型對象,可以像變數一樣進行賦值比較等操作。
不能寫匿名函數。
Math需要用Mathf。
3.類(DOM js中沒有類):
在Unity里,一個js文件就是一個類,unity引擎會為js文件自動生成一個類。
對於UnityScript腳本,Unity編譯該文件時會自動的為腳本添加一個與腳本文件名相同的類,並自動地繼承於MonoBehaviour。但對於C#或Boo,則需要在腳本中顯式的寫出類名和繼承關系。要創建不繼承自MonoBehaviour的類,用C#語言,或者從外部添加js腳本資源(就可以自己直接new對象出來了)。
//SayHello.js
#pragma strict // 嚴格類型檢測,盡早生成錯誤,禁用動態類型,強制用靜態類型(強類型)
function sayHello()
{
}
等價於C#中:
#pragma strict
public class SayHello extends MonoBehaviour
{
function sayHello()
{
}
}
但是,你可以在同一個文件中聲明多個類,尤其是當你需要使用一些輔助工具類時非常有用,一般這種輔助類沒有繼承自MonoBehaviour。

class ButtonState {
var currentState : int;
var offset : Vector2;
}
如果你在一個文件中聲明了MonoBehaviour的子類,但類名與文件名不匹配的話,即使是大小寫不一致,你也會碰到麻煩。
一定要理解,當你在js文件中編寫行為腳本是,你實際上在編寫一個類:
a) 類及其對象:文件名就是類名,如果文件名是foo.js,你就可以在其他地方以var x = new foo()的格式進行調用;
b)類的方法和預定義方法:有一些特定的方法是實現系統預先定義的一些事件處理器,如Start、FixedUpdate等。任何事件中,聲明的一個函數就是這個文件所代表的類的一個方法。
c) 類的屬性:文件中在函數定義之外編寫的代碼都在該類的范圍之內執行,聲明的變數也是該類的成員變數。類中的靜態函數、變數本質上是類的方法與屬性。
實例:
/*whenyou drag the behavior onto a gameobject, these values will be visible andeditable
*/
public name : String;
/*otherscripts which have a reference to this object (e.g. if they're attached to thesame object) can see public functions
*/
publicage : int;
/*privatemembers are NOT visible to other scripts, even if they have a reference to thisobject
*/
private favoriteColor : Color;
/*youcan assign a value to bestFriend by dragging a gameObject with an attached of the foo behavior to this property. This will give you access to bestFriend'spublic methods and members
*/
public bestFriend : foo;
/*this function will be called every frame by Unity, so it's actually an eventhandler
*/
function Update(){
/*transform is a property inherited from thegameObject the behavior is attached to*/
var t = transform;
}
function Bar(){
// this is just a function, if you don't callit yourself, it will never do anything
}
4.繼承
Unity里需要extends關鍵字:
class MyHello extends Hello
{
}
DOM js中用prototype里的bind()方法。
Unityjs裡面還提供了虛擬函數。
類的繼承也是不同的。在JavaScript和C#中,方法是隱型並且不可重載,除非方法聲明中添加虛擬關鍵字。不同的是C#只重載那些包含重載關鍵字override的方法。而JavaScript不需要關鍵詞,只要重載類方法就可以覆蓋,其它的都可繼承得到。
//Foo.js
var foo = "hello, world";
function doEet () {
// does nothing, intended to be overridden
}
將會生成:
//Foo.js
import UnityEngine;
classFoo extends MonoBehaviour {
public var foo = "hello, world";
public function doEet () {
// does nothing, intended to be overridden
}
}
子類寫法:
//PrintingFoo.js
class PrintingFoo extends Foo {
function doEet() {
print( foo );
}
}
創建虛函數:
classFoo
{
virtual function DoSomething ()
{
Debug.Log("from baseclass");
}
}
//SubFoo.js
class SubFoo extends Foo
{
virtual function DoSomething()
{
Debug.Log("from subclass");
}
}
//Elsewhere
varfoo : Foo = new SubFoo();
foo.DoSomething();//printsfrom sub class
如果你要調用父類的方法,用關鍵字super。示例如下:
class SubFoo extends Foo
{
virtual function DoSomething()
{
super.DoSomething();// 不是虛函數,應該不需要super修飾就可以直接調用。
Debug.Log("from sub class");
}
}
//Elsewhere
varfoo : Foo = new SubFoo();
foo.DoSomething();//prints"from base class" and "from sub class"
類間通信:Use-a方式(關聯關系)比繼承耦合度底得多,易於修改維護
/*Foo.js */
varbar : Bar;
function Start(){
bar = gameObject.GetComponent(Bar);
}
function doEet(){
// do my own thing
if( bar ){
bar.doEet();
}
}
/*Bar.js */
function doEet(){
// do something special
}
5.對象
Unity中不一定可以用new 創建對象(普通類可以,特殊類不行,各種腳本都一樣)。特殊類:用編輯器工程視圖右鍵或者組件Create js 或者C#的類都是繼承自MonoBehaviour類,對這種類型的類不能new出來一個對象,原因是Unity會為這種類自動創建對象,並調用被重載的方法。
使得用Unity非常有趣的一件事是,它的類採用了非常自由的mixin策略。通常你可以非常快速簡單的查到你所需要的類。最通用的一個例子是Transform類,對於你正在處理的一個對象,所有被附加到該對象的相關聯的類,都可以簡單快速的獲取它的屬性和方法。
比如,典型的動作就是你會訪問名叫"transform"的變數,它代表與該對象關聯的Transform類的實例。如果你需要相關的位置坐標,就訪問transform.position(一個 Vector3對象);如果你需要它的GameObject,就訪問transform.gameObject;如果你需要它的渲染器,就訪問transform.renderer。等等。一般如果你一個對象的主要屬性,你就可以快速獲取該對象所有其他的屬性。
6.js和C#單向通信,不能雙向通信,因為編譯問題
js訪問C#腳本組件:
//createa variable to access the C# script
private var csScript : CSharp1;
function Awake()
{
//Get the CSharp Script
csScript =this.GetComponent("CSharp1");//Don't forget to place the 'CSharp1'file inside the 'Standard Assets' folder
}
//rendertext and other GUI elements to the screen
function OnGUI()
{
//render the CSharp1 'message' variable
GUI.Label(new Rect(10,30,500,20),csScript.message);
}
C#訪問js腳本組件:
using UnityEngine;
using System.Collections;
public class CSharp2 : MonoBehaviour
{
//create a variable to access the JavaScriptscript
private JS1 jsScript;
void Awake()
{
//Get the JavaScript component
jsScript = this.GetComponent<JS1>();//Don'tforget to place the 'JS1' file inside the 'Standard Assets' folder
}
//render text and other GUI elements to thescreen
void OnGUI()
{
//render the JS1 'message' variable
GUI.Label(newRect(10,10,300,20),jsScript.message);
}
}
7.使用第三方庫:
第三方.NET庫如XML-RPC可以以新建資源Asset的方式引入。
8.調試
可以用print函數,Log()函數或者Debug.Log(),想設置斷點,用Debug.Break()函數。
print() 函數將會生成消息,並輸出到狀態欄及控制台中,但僅限MonoBehavioour類范圍內。
更好的辦法是使用Debug.Log("insert messagehere");,該方法到處都可使用。還可用Debug.LogWarning 和 Debug.LogError生成警告和錯誤消息。
Debug.Break(); 可以將游戲暫停在一個精確的點。當一種特定的情條件發生時,如果你想檢查對象的狀態的時候,這個特性非常有用。
開發環境運行項目時,編輯界面也是完全實時更新的,你可以查看對象實例的內部狀態。

㈤ 我想學習編程,但是不知道該怎麼開始。

我建議最好是從基礎入手,而不是一開始就進行可視化編程。雖然如今國內絕大多數pc都是使用的windows,但是畢竟這知識這個世界的冰山一角。扎實的基礎自然會更有用處。編程其實重要的是程序思維,然後是演算法和數據結構。這些都是超出語言的,就是說不管是學c學java學delphi還是別的什麼,這一部分都是一致的。因此培養這部分的知識可以說是一本萬利的事情。初學肯定是通過語言熟悉思想熟悉演算法和數據結構,到一定的時候就是純粹的思想和演算法數據結構的學習,便已經脫離程序語言了。經歷過這些階段,換一種語言不過是重新了解一下描述的方式,就像你了解了中文思維,山東話和四川話的差別就不會太大;了解了拉丁語的思維,整個語系的語言都不過是簡簡單單的記憶工作,應用就好。入門的語言,理論上是怎麼方便學哪個,看那個順眼學哪個。當然這裡面還是有不同的推薦的。一般來說我比較推薦pascal、c/c++、java。並不是因為這三個東西很通用很有前途,而是它們實在是嚴整而有規則(c/c++還顯得稍微的寬鬆了一點),而嚴謹的語法要求和明確的概念區分是有利於編程思維的形成和演算法數據結構的學習的。同樣的因為這個理由我不推薦vb,而並不是因為它功能不強大(事實上vb在windows環境中是相當牛的語言)另外一個建議是,如果學c,不要一開始就用vc。ms提供的很多東西很方便,有很多很簡單的實現方法,但是它們不標准。vc與ansi
c標準是有很大的差距的。首先一個不遵循標準的c/c++程序是不通用的,換個編譯器說不定就不被承認了。所以我非常推崇gcc,理由之一是它完全符合
ansi
c標准,無論它的c還是c++編譯器都很嚴整,功能上一點也不缺乏(有人說gcc不能做圖形界面的程序,這一點完全錯誤,到處都有的qt庫和gtk庫都能做出很好的界面),另外一個理由便是它免費,畢竟稍微大一點的軟體企業就不會屈從與微軟的編譯器和平台,而一個免費的c編譯器無疑可以創造更多的利益;就算要轉vc,標準的c程序也是幾乎不要作任何改動的。當然,這一切的前提是,你真的很想很好的學編程,做一個這方面的精英。如果只不過是興趣,或者只是想拿一個ms的工程師認證然後在國內企業找份諸如設計vf、vb程序之類的工作,那完全可以忽略我上面的話,去找個認證培訓班,認認真真聽聽課,好好完成練習,從vb或者vc入手,考好認證是很不會太難的。畢竟現在很多很好的大學里都從來不缺乏計算機的課程,不會缺少演算法或者編譯原理的課程,不會沒有計算機科學的研究院,而那裡面出來的人一般都具備了很好的基礎知識,會更加容易成為前面所說的精英。

熱點內容
java位與運算 發布:2025-02-08 18:48:22 瀏覽:214
sift演算法詳解 發布:2025-02-08 18:35:23 瀏覽:579
linux標准錯誤的是 發布:2025-02-08 18:32:07 瀏覽:915
蠻多小說怎麼緩存書架的小說 發布:2025-02-08 18:30:16 瀏覽:888
光遇花開腳本封號嗎 發布:2025-02-08 18:23:15 瀏覽:534
怎麼弄ld帳號和密碼 發布:2025-02-08 18:11:42 瀏覽:628
新逍客20發動機壓縮比 發布:2025-02-08 17:58:10 瀏覽:115
qq號和密碼我都知道為什麼登不上 發布:2025-02-08 17:52:21 瀏覽:872
寶塔伺服器ip進不去 發布:2025-02-08 17:52:18 瀏覽:382
擔保中介源碼 發布:2025-02-08 17:14:37 瀏覽:413