Giter VIP home page Giter VIP logo

3dactiongame's People

Contributors

athenaeum-school avatar inotakuya avatar nadd3564 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

3dactiongame's Issues

namespaceの追加について

単体テストを行うためにコードを若干整理していただきたく思います。

namespace Cradle {}
namespace Cradle.FSM {}
namespace Cradle.server {}

といったように、コードをnamespace内に入れて頂けますと助かります。

JSON通信 UnityからのPostについて

下記のスクリプトでTCサーバーにPostが失敗します。
最下段付近のDebug.Logメソッドで確認した所、

WWW Error: 400 Bad Request
UnityEngine.Debug:Log(Object)
c__Iterator6:MoveNext() (at Assets/Script/Server/JSONSampleWeb.cs:58)

と表示されます。
自分なりにUnity WWW Error: 400 Bad Requestというワードで調べ、海外のフォーラム等も目を通しましたが、解決には至りませんでした。

力をお貸し頂きたいです。宜しくお願い致します。

                    ----- JSONSampleWeb.cs ------
using UnityEngine;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using MiniJSON;

public class JSONSampleWeb : MonoBehaviour {

void Start () {
    // コルーチン実行開始
    StartCoroutine(GetJSON("http://localhost:8080/Cradle/json/4"));
    StartCoroutine(PostJSON("http://localhost:8080/Cradle/json/"));
}

IEnumerator GetJSON(string url){
    // HEADERはHashtableで記述
    Hashtable header = new Hashtable ();
    header.Add ("Accept-Language", "ja");

    // 送信開始
    WWW www = new WWW (url, null, header);
    yield return www;

    // webサーバからの内容を文字列変数に格納
    var json = Json.Deserialize(www.text) as IDictionary<string, object>;
    Debug.Log (www.text);
}

IEnumerator PostJSON(string url){

    // HEADERはHashtableで記述
    Hashtable header = new Hashtable ();
    header.Add ("Content-Type", "application/json; charset=UTF-8");

    JSONObject obj = new JSONObject();
    obj.AddField ("itemName", "カタナ");
    obj.AddField("itemType", "武器");
    obj.AddField("price", 100);
    obj.AddField("attack", 10);
    obj.AddField("defence", 10);
    obj.AddField("description", "はやい");

       //Jsonオブジェクト化
string postJsonStr = MiniJSON.Json.Serialize(obj);
Debug.Log (postJsonStr);
       //バイトへ変換
byte[] postBytes = System.Text.Encoding.UTF8.GetBytes (postJsonStr);

    // 送信開始
    WWW www = new WWW (url, postBytes, header);
    yield return www;


    // 成功
    if (www.error == null) {
        Debug.Log("WWW Ok!: " + www.data);
    }
    // 失敗
    else{
        Debug.Log("WWW Error: "+ www.error);          
    }

}

}

統合テスト(Integration Test)について

単体テストは終わったようですので、統合テストができるとよりよいと思います。

以下のような簡単なテストをして、慣れてからテストに入るとやりやすいと思いますのでご検討ください。

http://files.unity3d.co.jp/blog/Unityテストツール%20ドキュメンテーション.pdf

  • Main characterのrendererがカメラによってレンダリングされてるかテスト
  • GameManagerオブジェクトの子オブジェクトが、親オブジェクトが同一かのテスト
  • 敵が一定距離になるとプレーヤーに近づくかテスト (サンプルのシーンを用意する)
  • 敵が攻撃するとプレーヤーにダメージを与えるかテスト
  • 地面と接触しているかテスト (敵+Main Character)
  • Assertion Componentを使って、フィールドの値をテスト
    例えば、Transform.position.yの値が0以上かのテスト

人口知能FSMの単体テストについて

お疲れ様です。

まずAdvancedFSMについての内容ですが、これがabstract classだから問題という認識でしたが、通常のクラスだったようなので、

  • interface
  • controller

に必要部分を分離する必要があります。おそらくFSMState由来のクラスが抽象だったのが、誤認の原因かと思います。

FSMState由来のオブジェクトのメソッドについては、モック@nsubstituteを使って擬似的に動作をシミュレーションさせるのが一番早いと思います。

またFSMStateそのものを単体テストする場合は、

  • サブ(継承)クラス==xxStateクラス経由で、FSMStateのテスト(簡単ですが、やや単体テストの趣旨からは外れます、しかしテスト毎に使うモックを分けることにより、色々なバラエティーが出てくるので、直観的に理解しやすく総じて良いテストになる可能性があります)
    または
  • 直接モックとして、テスト対象するメソッド内のメソッド・オブジェクト等の行動を定義して、テストを実行(これも若干テストの趣旨からずれる可能性があり、テストパターンが限定される可能性があります)
  • interfaceに分離してから、Unity由来のオブジェクトをモックにしてからテスト、必要であればcontrollerなどに再分離してテスト

の3つがあるかとは思います。難易度でいえば、サブクラス、interface・controller分離、直接といった方式になるかと思いますので、時間を考えるとサブクラス方式が一番よいかと考えます。ただし、Unity由来のオブジェクト・メソッドはやはり、モックする必要があると思います。

最後に人口知能AdvancedFSMの継承クラス==NPCクラスのConstructFSMについては、極めて面倒ですが、外部クラス・メソッドは全てMock(擬似オブジェクト)にしておき、さらに処理部分を一つ一つ分割して新たなメソッドにいれていく必要があると思います。つまり、ここでは相当なリファクタリングが必要とされます。

最後にあまり時間がかかりすぎるようであれば、ほどほどで単体テストは切り上げて、統合テストに入っていただくのが良いかと思います。

マージ依頼

サーバー側のコードを追加しました。
都合のよろしい時にマージしてください。

状態マシンの組み込みについて

現在は画面遷移の状況については、ご本人にしか把握するのが難しい状況だと思います。

状態マシンを導入いただき、画面遷移図なども頂けますと理解の助けになるかと思いますので、ご検討いただけますと助かります。

JSON関連の単体テストの追加について

サーバー側の単体テストですが、認証については以下の部分が使えると思料します。

http://spring.io/guides/tutorials/rest/5/

Test for security

You already have a functional test from Step 4 that attempts to access your running RESTful service. As HTTP Basic authentication requires you to add some new headers, you'll first extract the creation of those headers for the HTTP request into a separate method called getHeaders:

src/test/java/com/yummynoodlebar/rest/functional/OrderTests.java

static HttpHeaders getHeaders(String auth) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

byte[] encodedAuthorisation = Base64.encode(auth.getBytes());
headers.add("Authorization", "Basic " + new String(encodedAuthorisation));

return headers;

}

While containing the previous code's JSON-based headers, it adds an Authorization header driven by an input parameter. This way, it is easy to test different security parameters from different test methods:

Finally you can update the original test to use the new getHeaders helper method to add security headers to your outgoing HTTP request:

src/test/java/com/yummynoodlebar/rest/functional/OrderTests.java

@test
public void thatOrdersCanBeAddedAndQueried() {

HttpEntity<String> requestEntity = new HttpEntity<String>(
    RestDataFixture.standardOrderJSON(),
    getHeaders("letsnosh" + ":" + "noshing"));

RestTemplate template = new RestTemplate();
ResponseEntity<Order> entity = template.postForEntity(
"http://localhost:8080/aggregators/orders",
requestEntity, Order.class);

String path = entity.getHeaders().getLocation().getPath();

assertEquals(HttpStatus.CREATED, entity.getStatusCode());
assertTrue(path.startsWith("/aggregators/orders/"));
Order order = entity.getBody();

System.out.println ("The Order ID is " + order.getKey());
System.out.println ("The Location is " + entity.getHeaders().getLocation());

assertEquals(2, order.getItems().size());

}

You can do this by creating a request that you know should fail if security is enabled, and check that it does.

JSONの形式

JSONの形式はこちらになります。

HTTP/1.1 200 OK
Server Apache-Coyote/1.1 is not blacklisted
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 15 Sep 2014 06:33:10 GMT

{"itemId":1,"itemName":"ルーンソード","itemType":"武器","price":300,"attack":10,"defense":0,"description":"攻撃力が10上昇する","updateTime":1410346214000}

state enumについて

Player/Enemyの状態(例:walkingなど)で2つの重複したenum宣言があるので、Interfaceやclassにまとめて一箇所で管理したほうが良いかとおもいます。AI FSMで使ったインターフェースなどが参考になると思います。

単体テスト、enum型について

お疲れ様です。

enum型はテストできませんでしょうか?
自分なりに試してみたのですが、テスト側から、コントローラーにあるenum型にアクセスできないように感じました。

public enum ItemKind
{
Attack,
Heal,
};
このenum型をMonoBehaviour継承クラスからコントローラーへ移し、

[TestFixture]
[Category ("DropItem Test")]
public class DropItemTest
{
public DropItemController.ItemKind kind;

    [SetUp] public void Init()
    { 
        kind = new DropItemController.ItemKind ();
    }

このようにテストでインスタンスを生成しましたが、kind.でアクセスが出来ませんでした。(.ItemKindを省いて
試しても出来ませんでした。)
AIFSMのステート関連のメソッドが頻繁にenumに定義してあるキーを参照しているため、
テストする上で悩んでおります。

恐れ入りますが、ご指導のほど、よろしくお願いします。

ゲームの動作について

私環境外でも同じ動作をするよう更新しました。(サブ機にて確認済み)
1点、プレイヤーのテクスチャーだけついておりませんが、レポジトリのREADMEに詳細を記載しましたので、
お手数おかけしますが、ご留意頂けるよう宜しくお願いいたします。

*尚、フリーアセットをインポートせずそのままで動作します。

サーバーコンポーネントのアーキテクチャーについて

現在のサーバーは、データベース、通信、アプリケーションが単一に収まっていますが、大量処理やアプリケーションの将来的な拡張を想定としたエンタープライズ環境での実装があっても良いかと考えます。

エンタープライズ環境=役割ごとにサーバーが存在、サーバー間での通信が必要

そこで、EIP(Enterprise Integration Pattern:エンタープライズ・インテグレーション・パターン)/ESB(Enterprise Service Bus:エンタープライズ・サービス・バス)といった、手法が考えられます。

例えば、クライアント(Unity)側からの通信が、JSON/XML@REST以外の型式だったと仮定し以下のような通信形態もサポートし、

①FTP (例:音声・画像ファイル等)
②SMTP
③SOAP
④C#側でシリアル化したデータ@特定TCPポート(例:サーバー側でゲーム内情報を送信)
⑤HTTPで、定式化された文字列を本文に設置
⑥JMS@ActiveMQ(AMQ)
⑦ファイルシステムへのポーリング

かつ、サーバー側では、クライアントからののメッセージをSpring Frameworkでの受信したのちに他のサーバーにPub/Subモデルで同時配信するか、受信先がわかっていれば複数のP2Pで通信をするという想定での開発は極めて面倒です。

今回は、クライアント側の開発者が熱心ということもあって、色々ご協力頂けるかと思いますので、今後の方針としては、EIPコンセプトの導入としたいと思います。

WWWFormを使ったユーザー認証について

ユーザー認証についてですが、時間があればProxyパターンを使う方法もあるとは思いますが、下記のWWWFormを使えば、基本認証は行えると考えますので、ご検討いただけますでしょうか。

http://docs.unity3d.com/ScriptReference/WWWForm-headers.html

var form = new WWWForm();
form.AddField("name","value");
var headers = form.headers;
var rawData = form.data;
var url = "www.myurl.com";

// Add a custom header to the request.
// In this case a basic authentication to access a password protected resource.
headers["Authorization"]="Basic " + System.Convert.ToBase64String(
System.Text.Encoding.ASCII.GetBytes("username:password"));

// Post a request to an URL
var www = new WWW(url, rawData, headers);
yield www;
//.. process results from WWW request here...

MockのReceive,DidNotReceiveメソッドの活用について

NSubstituteでは処理されたかの成否と、処理された回数をテストできるReceive系のメソッドがあるので、お時間があれば、単体テストに組み込むと良いかと思います。

http://nsubstitute.github.io/help/received-calls/

        [Test]
        public void MultipleFireWorks ()
        {
            var gunController = GetGunMock ();
            var motor = GetControllerMock (gunController);

            motor.ApplyFire ();
            motor.ApplyFire ();
            motor.ApplyFire ();

            gunController.Received (3).Fire ();
        }

        [Test]
        public void CanNotFireWithNotBullets ()
        {
            var gunController = GetGunMock ();
            var motor = GetControllerMock (gunController);
            motor.bulletsLeft = 0;

            gunController.ClearReceivedCalls ();
            motor.ApplyFire ();

            gunController.DidNotReceive ().Fire ();
        }

        [Test]
        public void ReloadWorks ()
        {
            var gunController = GetGunMock ();
            var motor = GetControllerMock (gunController);
            motor.bulletsLeft = 0;

            motor.ApplyReload ();
            Assert.That (motor.bulletsLeft, Is.Not.EqualTo (0));
        }

単体テストについて @CharaAnimation

本日ご指摘頂きました、Updateメソッド内のif文の分離を試みておりましたが、なかなか上手くいきません。
ご教授頂きたく、お願い申し上げます。

   CharaAnimation.cs
*不要な部分は割愛してあります。

CharaStatus status;

if(isAttacked() && !status.IsAttacking()){
isSetAttacked(false);

こちらを、CharaAnimationControllerの方に移植を試み、
     
     CharaAnimationController.cs

public void StopAttack(){
if (IsAttacked () && !status.IsAttacking ()) {
IsSetAttacked (false);
}
}

このようにしましたが、status.IsAttackingがモノベハビア継承の外部クラス(CharaStatus.cs)のインスタンスのため、エラーになります。

コントローラー内でモノベハビアに関連するものが入れられないため、どうすべきか悩んでおります。

現状、ChataStatusContorollerにIsAttackingを移植し、そこにアクセスする形で呼び出す方法を考えていますが、その方法は使ってもよろしいでしょうか?

Scripts下のフォルダー

単体テストについてですが、

CharaStatus.cs であれば、

public class CharaStatus : MonoBehaviour, IEffectController {}
public class CharaStatusController {}

といった形にコードのロジックを分散したリファクターしてテストをしたいと考えています。このためIEffectController、CharaStatusControllerなどの追加が必要です。

今のフラットなフォルダ階層だと見栄えがよくないので、Controllerフォルダや、Interfaceフォルダがあったほうがいいと思いますが、いかがでしょうか。

JSONObjectのエラーについて

JSonObjectからエラーが出ており、テストができませんので、TBブランチではJSONObjectおよび、関連コードを削除することにしました。これによりエラーが回復するまでは、当面マージはしないほうが良いかと思います。

c:\Users.....\GitHub\TB\Assets\Plugins\JSON\JSONObject.cs(59,59): Error CS0241: 既定のパラメータ指定子は使用できません。 (CS0241) (Assembly-CSharp-firstpass)

Compiler Error CS0241
Visual Studio 2008
Other Versions
2 out of 4 rated this helpful - Rate this topic

Default parameter specifiers are not permitted

Method parameters cannot have default values. Use method overloads if you want to achieve the same effect. For more information, see Passing Parameters (C# Programming Guide).
Example

The following sample generates CS0241. In addition, the sample shows how to simulate, with overloading, a method with default arguments.

// CS0241.cs
public class A
{
public void Test(int i = 9) {} // CS0241
}

public class B
{
public void Test() { Test(9); }
public void Test(int i) {}
}

public class C
{
public static void Main()
{
B x = new B();
x.Test();
}
}

JSON通信について

JSONでの通信ですが、POST.PUT.DELETEもできるようになったので、
確認お願いします。

デザインパターンの組み込み(Memento)

Mementoパターンの実装についての課題を開いておきます。

先日お話した際は、Deep Copy(オブジェクト内のオブジェクト=referenceもコピー)を使う手法をお話しましたが、別途データを保管するクラスを用意して、そこで各ゲームオブジェクトのデータを前の時点に復帰(再設定)
するためのメソッドなどを実装するのが、良いかと思います。

方針が決まりましたら、こちらの課題でご説明頂き、開発・実装状況をお伝え頂けますと助かります。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.