Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
Unity½áºÏFlaskʵÏÖÅÅÐаñ¹¦ÄÜ
 
ÒëÕߣºCode Cabin À´Ô´£º51Testing ·¢²¼ÓÚ 2015-03-23
  3535  次浏览      27
 

ÒµÓà×öµÄСÓÎÏ·£¬ÅÅÐаñ±¾À´ÊÇÓÃPlayerPrefs´æ´¢ÔÚ±¾µØ£¬ÏÖÔÚÏ뽫Êý¾Ý·ÅÔÚ·þÎñÆ÷ÉÏ¡£ÒòΪ¹¦Äܼܺòµ¥£¬¾ÍÑ¡ÔñÁËСÇÉÁáççµÄFlaskÀ´ÊµÏÖ¡£

Ïл°ÉÙÐð¡£Ê×ÏÈ¿¼ÂÇURLµÄÉè¼Æ¡£ÅÅÐаñÎÞ·ÇÊÇÒ»¶Ñ·ÖÊýscoreµÄ¼¯ºÏ£¬°´ÕÕRESTµÄ˼Ï룬²»·Á½«URLÉèΪ/scores¡£ÓÃGET»ñµÃÅÅÐаñÊý¾Ý£¬ÓÃPOSTÌí¼ÓÒ»Ìõмͼµ½ÅÅÐаñ¡£´ËÍ⣬°´ÕÕ¹ßÀý£¬ÅÅÐаñµÄÊý¾Ý²»ÐèÒª¸üкÍɾ³ý¡£

Flask×ÔÉí²»Ö§³ÖREST£¬µ«ÎÒÃÇ¿ÉÒÔͨ¹ýrouteºÍmethod×Ô¼ºÊµÏÖ¡£ÏÂÃæ´´½¨Ò»¸öÔ­ÐͰ汾µÄrank_server.py¡£ÃüÃûÑØÏ®ÁËRailsµÄϰ¹ß£º

from flask import Flask
¡¡¡¡app = Flask(__name__)
¡¡¡¡@app.route('/scores', methods=['GET'])
¡¡¡¡def index():
¡¡¡¡return 'index'
¡¡¡¡@app.route('/scores', methods=['POST'])
¡¡¡¡def create():
¡¡¡¡return 'create'
¡¡¡¡if __name__ == '__main__':
¡¡¡¡app.run(debug=True)

Ö´ÐÐpython rank_server.pyÀ´Æô¶¯×Ô´øµÄ·þÎñÆ÷¡£ÏÂÃæÎÒÃǰ²×°cURLÀ´²âÊÔÓ¦Óá£

¡¡brew install curl

²âÊÔGET£º

`curl -i -X GET 127.0.0.1:5000/scores`

²âÊÔPOST£º

`curl -i -X POST 127.0.0.1:5000/scores`

¡¡-i²ÎÊý¿ÉÒÔչʾÏìÓ¦µÄÍ·²¿ÐÅÏ¢£¬±ãÓÚdebug¡£-X²ÎÊýÖ¸¶¨ÇëÇóµÄ·½·¨method¡£

¿ÉÒÔ¿´µ½²âÊԳɹ¦¡£

ÏÂÃæÎÒÃǽ¨Á¢´æ´¢Êý¾ÝµÄ±í¡£±¾µØ²âÊÔÎÒÃÇʹÓÃsqlite£¬Ö®ºó²¿ÊðʹÓÃmysql¡£

½¨±íÎļþcreate_rank.sqlÄÚÈÝÈçÏ£º

DROP TABLE IF EXISTS rank;
¡¡¡¡CREATE TABLE rank(
¡¡¡¡id INTEGER PRIMARY KEY AUTOINCREMENT,
¡¡¡¡name VARCHAR(255) NOT NULL,
¡¡¡¡score INTEGER NOT NULL
¡¡¡¡);

¡¡Mac×Ô´øsqlite¡£Ö´ÐÐÏÂÃæÓï¾äµ¼ÈësqlÎļþ£º

sqlite3 rank.db < create_rank.sql

È»ºóËæ±ã²åÈ뼸Ìõ²âÊÔÊý¾Ý¡£È磺

INSERT INTO rank (name, score) VALUES ('A', 100);
¡¡¡¡INSERT INTO rank (name, score) VALUES ('B', 200);
¡¡¡¡INSERT INTO rank (name, score) VALUES ('C', 300);

Õë¶ÔÊý¾Ý¿â£¬ÎÒÃÇÔÚrank_server.pyÖмÓÈëÏÂÃæÒ»¶Î´úÂ룬ÓÃÓÚÔÚÇëÇóǰºó´¦ÀíÊý¾Ý¿âÁ¬½Ó¡£

import sqlite3
¡¡¡¡DATABASE = 'rank.db'
¡¡¡¡@app.before_request
¡¡¡¡def before_request():
¡¡¡¡g.db = sqlite3.connect(DATABASE)
¡¡¡¡@app.teardown_request
¡¡¡¡def teardown_request(exception):
¡¡¡¡if hasattr(g, 'db'):
¡¡¡¡g.db.close()

ÎÒÃǹ涨·þÎñÆ÷ºÍ¿Í»§¶ËʹÓÃJSON´«ÊäÊý¾Ý¡£

GETÇëÇ󷵻صÄJSON¸ñʽÈçÏ£º

{
"data":
[
{
"id": 0,
"name": "A",
"score": 100
},
{
"id": 1,
"name": "B",
"score": 200
}
]
}

ÕâÀïµÄidÆäʵÊÇ×ÔÔöÖ÷¼ü£¬¿ÉÒÔ²»±Ø±£Áô£¬µ«ÎªÁ˺óÃæ´¦Àí·½±ã¾ÍÒ»Æð±£ÁôÁË¡£

POSTÌá½»µÄJSON¸ñʽÈçÏ£º

{
¡¡¡¡"id": 0,
¡¡¡¡"name": "C",
¡¡¡¡"score": 300
¡¡¡¡}

ÏÖÔÚÎÒÃÇ¿ÉÒÔ×ÅÊÖʵÏÖindex·½·¨ÁË£º

def index():
¡¡¡¡cur = g.db.execute('select id, name, score from rank order by score desc;')
¡¡¡¡result = cur.fetchmany(100)
¡¡¡¡data = []
¡¡¡¡for row in result:
¡¡¡¡data.append({'id': row[0], 'name': row[1], 'score': row[2]})
¡¡¡¡return jsonify({'data': data})

£¨ÆäÖÐjsonifyºÍgÔÚflaskÄ£¿éÄÚ¡£ºóÃæ²»ÔÙ¶Ôµ¼Èë½øÐÐ˵Ã÷£¬Ä¬È϶¼ÊÇ´Óflaskµ¼Èë¡££©

ÔÚ²éѯʱ¶ÔÊý¾Ý×öÁËÅÅÐò£¬²¢ÇÒÖ»·µ»ØÁËǰ100Ìõ¼Ç¼¡£¿ÉÒÔÓÃcurlÔÙ²âÊÔһϡ£²âÊÔÎÞÎóÔÙʵÏÖcreate·½·¨£º

def create():
¡¡¡¡status = {'status': 'OK'}
¡¡¡¡if not request.json or not 'name' in request.json or not 'score' in request.json:
¡¡¡¡status['status'] = 'bad request'
¡¡¡¡try:
¡¡¡¡g.db.execute('insert into rank (name, score) values (?, ?)', [request.json['name'], request.json['score']])
¡¡¡¡g.db.commit()
¡¡¡¡except:
¡¡¡¡status['status'] = 'database error'
¡¡¡¡return jsonify(status)

ÎÒÃǵÄPOSTÇëÇó¶¼ÊÇJSONÀàÐ͵ģ¬ËùÒÔÒª´Órequest.json»ñµÃ£¬¶ø²»ÊÇargs»òÕßform¡£´ËÍ⣬·µ»ØÁËÒ»¸östatus±äÁ¿£¬±ãÓڲ鿴³ö´íÔ­Òò¡£

ÔÙÓÃcurl²âÊÔÒ»ÏÂPOST¡£Õâ´Î£¬ÎÒÃÇÒªÏòPOSTÇëÇóÖмÓÈëÊý¾Ý£º

curl -i -X POST -H "Content-Type: application/json" -d '{"id": 0, "name": "xyz", "score": "800"}' 127.0.0.1:5000/scores

-H²ÎÊýÓÃÓÚÖ¸¶¨Í·²¿ÐÅÏ¢£¬-d²ÎÊý¿ÉÒÔЯ´øÊý¾Ý£¬ÕâÀï¾ÍÊÇÒ»Ìõ·ûºÏÎÒÃÇÌá½»¸ñʽµÄJSONÊý¾Ý¡£

ÏÖÔÚ·þÎñÆ÷¶Ë¾Í£¨ÔÝʱ£©ÊµÏÖÍêÁË¡£ÏÂÃæ¸ÃдC#´úÂëÀ²¡£

ÎÒÃÇÐèÒªÉè¼ÆÒ»¸öºÍ·þÎñÆ÷½»»¥¡¢²¢·µ»ØÊý¾Ý¸øUI²ãµÄÀà¡£

Ê×ÏÈ£¬Õâ¸öÀàÓ¦¸ÃÊǵ¥ÀýµÄ£¬Òª¼Ì³ÐMonoBehaviour£¨ÒòΪºÍ·þÎñÆ÷½»»¥ÒªÀûÓÃCoroutine£©£»¶øÇÒ×îºÃ¶ÀÁ¢ÓÚ³¡¾°Ö®Íâ¡£¹ØÓÚUnityÖÐʵÏÖµ¥ÀýÀàµÄ¼¯Öз½Ê½£¬Çë¿´ÎÒµÄÁíһƪÎÄÕ¡£µ¥ÀýµÄ´úÂëÈçÏ£º

private static SaveLoad _instance = null;
public static SaveLoad Instance {
get
{
if (_instance == null)
{
GameObject go = new GameObject("SaveLoadGameObject");
DontDestroyOnLoad(go);
_instance = go.AddComponent<SaveLoad>();
}
return _instance;
}
}

»¹ÐèÒª¶¨ÒåһЩ³£Á¿£º

const int recordsPerPage = 5;
¡¡¡¡const string URL = "127.0.0.1:5000/scores";

¶¨ÒåÒ»¸öÊý¾Ý½á¹¹£º

public struct Data {
¡¡¡¡public int id;
¡¡¡¡public string name;
¡¡¡¡public int score;
¡¡¡¡}

ÔÚ¶¯ÊÖ֮ǰ£¬»¹ÒªÁ˽âÁ½¸ö¶«Î÷£ºWWWÀàºÍLitJson¿â¡£WWWÀàÊÇUnity×Ô´øµÄ´¦ÀíHTTPÇëÇóµÄÀࣻLitJsonÊÇÒ»¸öC#´¦ÀíJSONµÄ¿ªÔ´¿â¡£ÒªÊ¹ÓÃLitJson£¬ÏÈ´Ó¹ÙÍøÏÂÔØdllÎļþ£¬È»ºóµ¼ÈëAsset¡£

SaveLoadÀàµÄ¹¦ÄܾÍÏñÃû×ÖÒ»Ñù£¬°üÀ¨±£´æSaveºÍÔØÈëLoad¡£

public void Save(Data data)
{
var jsonString = JsonMapper.ToJson(data);
var headers = new Dictionary<string, string> ();
headers.Add ("Content-Type", "application/json");
var scores = new WWW (URL, new System.Text.UTF8Encoding ().GetBytes (jsonString), headers);
StartCoroutine (WaitForPost (scores));
}
IEnumerator WaitForPost(WWW www){
yield return www;
Debug.Log (www.text);
}

ÕâÀï´´½¨WWWʵÀý£¬Ö¸¶¨ÁËURL¡¢headerºÍÌá½»Êý¾Ý¡£µÚÒ»ÐеÄJsonMapper¿ÉÒÔÔÚ¶ÔÏóºÍJSONÖ®¼ä½øÐÐת»»£¬Ç°ÌáÊǶÔÏóÖеÄÊôÐÔºÍJSONÖеļüÒª±£³ÖÒ»Ö¡£

public void Load()
{
var scores = new WWW (URL);
StartCoroutine(WaitForGet(scores));
}
IEnumerator WaitForGet(WWW www){
yield return www;
if (www.error == null && www.isDone) {
var dataList = JsonMapper.ToObject<DataList>(www.text);
data = dataList.data;
}else{
Debug.Log ("Failed to connect to server!");
Debug.Log (www.error);
}
}

Load·½·¨ÖÐÊǽ«Ç°Ãæindex·½·¨·µ»ØµÄJSONÎı¾×ª»»³É¶ÔÏó£¬ÕâÀïΪÁËʵÏÖת»»£¬Ð½¨Ò»¸öDataListÀ࣬ÆäÖеÄÊôÐÔÊÇList<Data>¡£

µ½ÕâÀ¿Í»§¶ËµÄ¶ÁÈ¡ºÍ±£´æÊý¾Ý¾ÍʵÏÖÁË¡£ÆäÓàµÄÂß¼­£¬±ÈÈçºÍUIµÄ½»»¥£¬ÔÚÕâÀï¾Í²»Ð´ÁË¡£¸ÐÐËȤµÄ¿ÉÒÔ¿´ÎÒµÄСÓÎÏ·µÄÍêÕû´úÂë

GitHub´«ËÍÃÅ

×îºó̸̸²¿ÊðµÄÊÂÇé¡£Èç¹ûÒª²¿Êðµ½SAEÓм¸µãҪעÒ⣺

´úÂëÒª½øÐÐÒ»¶¨µÄÐÞ¸ÄÒÔÊÊÓ¦MySQLdb¡£

ҪעÒâÖÐÎĵıàÂë¡£ÈçÓÃunicode·½·¨×ª»»Ãû×ÖÊôÐÔ£¬ÒÔ¼°ÎļþÍ·²¿µÄ£º

# -*- coding:utf8 -*-
¡¡¡¡#encoding = utf-8

×îºó˵˵±È½Ï¿ÓµÄUnity¿çÓò·ÃÎʵÄÏÞÖÆ¡£ÔÚÎҳɹ¦²¿Êðºó£¬curl²âÊÔûÓÐÎÊÌâÁË¡£½á¹ûUnity±¨ÁË´í£º

SecurityException: No valid crossdomain policy available to allow access

¾­¹ýÒ»·¬ËÑË÷£¬Ô­À´ÒªÔÚ·þÎñÆ÷µÄ¸ùĿ¼Ôö¼ÓÒ»¸öcrossdomain.xmlÎļþ¡£ÎļþÄÚÈÝ´óÖÂÈçÏ£º

<?xml version="1.0"?>
¡¡¡¡<!DOCTYPE cross-domain-policy SYSTEM
¡¡¡¡"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
¡¡¡¡<cross-domain-policy>
¡¡¡¡<site-control permitted-cross-domain-policies="master-only"/>
¡¡¡¡<allow-access-from domain="*"/>
¡¡¡¡<allow-http-request-headers-from domain="*" headers="*"/>
¡¡¡¡</cross-domain-policy>

µ«ÊÇSAEºÃÏñ²»Ö§³ÖÉÏ´«Îļþµ½¸ùĿ¼¡£Ö»ÄÜÓÃFlask·ÂðһÏÂÁË£º

@app.route('/crossdomain.xml')
¡¡¡¡def fake():
¡¡¡¡xml = """ÉÏÃæµÄÄǶÑÄÚÈÝ"""
¡¡¡¡return xml, 200, {'Content-Type': 'text/xml; charset=ascii'}
   
3535 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

΢·þÎñ²âÊÔÖ®µ¥Ôª²âÊÔ
һƪͼÎÄ´øÄãÁ˽â°×ºÐ²âÊÔÓÃÀýÉè¼Æ·½·¨
È«ÃæµÄÖÊÁ¿±£ÕÏÌåϵ֮»Ø¹é²âÊÔ²ßÂÔ
È˹¤ÖÇÄÜ×Ô¶¯»¯²âÊÔ̽Ë÷
Ïà¹ØÎĵµ

×Ô¶¯»¯½Ó¿Ú²âÊÔʵ¼ù֮·
jenkins³ÖÐø¼¯³É²âÊÔ
ÐÔÄܲâÊÔÕï¶Ï·ÖÎöÓëÓÅ»¯
ÐÔÄܲâÊÔʵÀý
Ïà¹Ø¿Î³Ì

³ÖÐø¼¯³É²âÊÔ×î¼Ñʵ¼ù
×Ô¶¯»¯²âÊÔÌåϵ½¨ÉèÓë×î¼Ñʵ¼ù
²âÊԼܹ¹µÄ¹¹½¨ÓëÓ¦ÓÃʵ¼ù
DevOpsʱ´úµÄ²âÊÔ¼¼ÊõÓë×î¼Ñʵ¼ù
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]

LoadRunnerÐÔÄܲâÊÔ»ù´¡
Èí¼þ²âÊÔ½á¹û·ÖÎöºÍÖÊÁ¿±¨¸æ
ÃæÏò¶ÔÏóÈí¼þ²âÊÔ¼¼ÊõÑо¿
Éè¼Æ²âÊÔÓÃÀýµÄËÄÌõÔ­Ôò
¹¦ÄܲâÊÔÖйÊÕÏÄ£Ð͵Ľ¨Á¢
ÐÔÄܲâÊÔ×ÛÊö


ÐÔÄܲâÊÔ·½·¨Óë¼¼Êõ
²âÊÔ¹ý³ÌÓëÍŶӹÜÀí
LoadRunner½øÐÐÐÔÄܲâÊÔ
WEBÓ¦ÓõÄÈí¼þ²âÊÔ
ÊÖ»úÈí¼þ²âÊÔ
°×ºÐ²âÊÔ·½·¨Óë¼¼Êõ


ij²©²ÊÐÐÒµ Êý¾Ý¿â×Ô¶¯»¯²âÊÔ
IT·þÎñÉÌ Web°²È«²âÊÔ
IT·þÎñÉÌ ×Ô¶¯»¯²âÊÔ¿ò¼Ü
º£º½¹É·Ý µ¥Ôª²âÊÔ¡¢Öع¹
²âÊÔÐèÇó·ÖÎöÓë²âÊÔÓÃÀý·ÖÎö
»¥ÁªÍøweb²âÊÔ·½·¨Óëʵ¼ù
»ùÓÚSeleniumµÄWeb×Ô¶¯»¯²âÊÔ